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

Revert to old tower keys #50

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,9 @@ btc_network = regtest

### Tower id and signing key

`teos` needs a pair of keys that will serve as tower id and signing key. The former can be used by users to identify the tower, whereas the latter is used by the tower to sign responses. These keys are automatically generated on the first run, and can be refreshed by running `teos` with the `--overwritekey` flag. Notice that once a key is overwritten you won't be able to use the previous key again*.
`teos` needs a pair of keys that will serve as tower id and signing key. The former can be used by users to identify the tower, whereas the latter is used by the tower to sign responses. These keys are automatically generated on the first run, and can be refreshed by running `teos` with the `--generatenewkey` flag.

\* Old keys are actually kept in the tower's database as a fail safe in case you overwrite them by mistake. However, there is no automated way of switching back to and old key. Feel free to open an issue if you overwrote your key by mistake and need support to recover it.
You can use an old key with the `--towerkey <keyindex>` option, where `keyindex` is the index of the desired secret key. The first tower secret key will have `keyindex` equal to `1` and subsequent keys will have their `keyindex` auto-incremented.

## Interacting with a TEOS Instance

Expand Down
2 changes: 1 addition & 1 deletion teos/src/conf_template.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ btc_rpc_port = 8332

# Flags
debug = false
overwrite_key = false
generate_new_key = false

# General
subscription_slots = 10000
Expand Down
23 changes: 17 additions & 6 deletions teos/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,16 @@ pub struct Opt {
#[structopt(long)]
pub debug: bool,

/// Overwrites the tower secret key. THIS IS IRREVERSIBLE AND WILL CHANGE YOUR TOWER ID
/// Generates a new secret key for the tower. This will change your tower ID
#[structopt(long)]
pub overwrite_key: bool,
pub generate_new_key: bool,

/// Index of the tower's secret key [default: None]
///
/// keyindex is the index of the secret key starting from 1 and is auto-incremented with each new key used.
/// Not specifying this option will let the tower choose the last known secret key.
#[structopt(long, conflicts_with = "generatenewkey", name = "keyindex")]
pub tower_key: Option<u32>,
}

/// Holds all configuration options.
Expand Down Expand Up @@ -132,9 +139,10 @@ pub struct Config {

// Flags
pub debug: bool,
pub overwrite_key: bool,
pub generate_new_key: bool,

// General
pub tower_key: Option<u32>,
pub subscription_slots: u32,
pub subscription_duration: u32,
pub expiry_delta: u32,
Expand Down Expand Up @@ -178,7 +186,8 @@ impl Config {
}

self.debug |= options.debug;
self.overwrite_key = options.overwrite_key;
self.generate_new_key = options.generate_new_key;
self.tower_key = options.tower_key;
}

/// Verifies that [Config] is properly built.
Expand Down Expand Up @@ -239,7 +248,8 @@ impl Default for Config {
btc_rpc_port: 0,

debug: false,
overwrite_key: false,
generate_new_key: false,
tower_key: None,
subscription_slots: 10000,
subscription_duration: 4320,
expiry_delta: 6,
Expand Down Expand Up @@ -270,7 +280,8 @@ mod tests {
data_dir: String::from("~/.teos"),

debug: false,
overwrite_key: false,
generate_new_key: false,
tower_key: None,
}
}
}
Expand Down
36 changes: 22 additions & 14 deletions teos/src/dbm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ use std::str::FromStr;

use rusqlite::ffi::{SQLITE_CONSTRAINT_FOREIGNKEY, SQLITE_CONSTRAINT_PRIMARYKEY};
use rusqlite::limits::Limit;
use rusqlite::{params, params_from_iter, Connection, Error as SqliteError, ErrorCode, Params};
use rusqlite::{
params, params_from_iter, Connection, Error as SqliteError, ErrorCode, Params, Row,
};

use bitcoin::consensus::deserialize;
use bitcoin::hashes::Hash;
Expand Down Expand Up @@ -571,22 +573,28 @@ impl DBM {
self.store_data(query, params![sk.to_string()])
}

/// Loads the last known tower secret key from the database.
/// Loads a tower secret key from the database.
///
/// Loads the key with higher id from the database. Old keys are not overwritten just in case a recovery is needed,
/// but they are not accessible from the API either.
pub fn load_tower_key(&self) -> Result<SecretKey, Error> {
let mut stmt = self
.connection
.prepare(
"SELECT key FROM keys WHERE id = (SELECT seq FROM sqlite_sequence WHERE name=(?))",
)
.unwrap();

stmt.query_row(["keys"], |row| {
/// Loads the secret key whose in-database id matches the index parameter.
/// If no index was passed, this will load the key with greatest id found in the database.
pub fn load_tower_key(&self, index: Option<u32>) -> Result<SecretKey, Error> {
let placeholder = match index {
Some(_) => "?",
None => "SELECT seq FROM sqlite_sequence WHERE name=('keys')",
};

let sql = format!("SELECT key FROM keys WHERE id = ({})", placeholder);
let mut stmt = self.connection.prepare(&sql).unwrap();

let f = |row: &Row| {
let sk: String = row.get(0).unwrap();
Ok(SecretKey::from_str(&sk).unwrap())
})
};

match index {
Some(id) => stmt.query_row([id], f),
None => stmt.query_row([], f),
}
.map_err(|_| Error::NotFound)
}
}
Expand Down
17 changes: 11 additions & 6 deletions teos/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,19 +97,24 @@ async fn main() {
DBM::new(path_network.join("teos_db.sql3")).unwrap(),
));

// Load tower secret key or create a fresh one if none is found. If overwrite key is set, create a new
// Load tower secret key or create a fresh one if none is found. If generate_new_key is set, create a new
// key straightaway
let (tower_sk, tower_pk) = {
let locked_db = dbm.lock().unwrap();
if conf.overwrite_key {
log::info!("Overwriting tower keys");
if conf.generate_new_key {
log::info!("Generating new tower keys");
create_new_tower_keypair(&locked_db)
} else {
match locked_db.load_tower_key() {
match locked_db.load_tower_key(conf.tower_key) {
Ok(sk) => (sk, PublicKey::from_secret_key(&Secp256k1::new(), &sk)),
Err(_) => {
log::info!("Tower keys not found. Creating a fresh set");
create_new_tower_keypair(&locked_db)
if let Some(key_index) = conf.tower_key {
eprintln!("No tower key of index {} found in the database.", key_index);
std::process::exit(1);
} else {
log::info!("Tower keys not found. Creating a fresh set");
create_new_tower_keypair(&locked_db)
}
}
}
}
Expand Down