2025-01-11 01:31:28 -05:00
|
|
|
use std::{path::Path, fs};
|
|
|
|
|
|
|
|
|
|
pub(crate) use serai_db::{Get, DbTxn, Db as DbTrait};
|
|
|
|
|
use serai_db::{create_db, db_channel};
|
|
|
|
|
|
2025-01-15 12:51:35 -05:00
|
|
|
use dkg::Participant;
|
|
|
|
|
|
2025-11-16 11:50:24 -05:00
|
|
|
use serai_client_serai::abi::primitives::{
|
|
|
|
|
crypto::KeyPair,
|
|
|
|
|
network_id::ExternalNetworkId,
|
|
|
|
|
validator_sets::{Session, ExternalValidatorSet},
|
2025-01-11 01:31:28 -05:00
|
|
|
};
|
|
|
|
|
|
2025-01-12 05:52:33 -05:00
|
|
|
use serai_cosign::SignedCosign;
|
2025-01-11 01:31:28 -05:00
|
|
|
use serai_coordinator_substrate::NewSetInformation;
|
2025-01-12 07:32:45 -05:00
|
|
|
use serai_coordinator_tributary::Transaction;
|
2025-01-11 01:31:28 -05:00
|
|
|
|
|
|
|
|
#[cfg(all(feature = "parity-db", not(feature = "rocksdb")))]
|
2025-01-15 12:10:11 -05:00
|
|
|
pub(crate) type Db = std::sync::Arc<serai_db::ParityDb>;
|
2025-01-11 01:31:28 -05:00
|
|
|
#[cfg(feature = "rocksdb")]
|
|
|
|
|
pub(crate) type Db = serai_db::RocksDB;
|
|
|
|
|
|
|
|
|
|
#[allow(unused_variables, unreachable_code)]
|
|
|
|
|
fn db(path: &str) -> Db {
|
|
|
|
|
{
|
|
|
|
|
let path: &Path = path.as_ref();
|
|
|
|
|
// This may error if this path already exists, which we shouldn't propagate/panic on. If this
|
|
|
|
|
// is a problem (such as we don't have the necessary permissions to write to this path), we
|
|
|
|
|
// expect the following DB opening to error.
|
|
|
|
|
let _: Result<_, _> = fs::create_dir_all(path.parent().unwrap());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(all(feature = "parity-db", feature = "rocksdb"))]
|
|
|
|
|
panic!("built with parity-db and rocksdb");
|
|
|
|
|
#[cfg(all(feature = "parity-db", not(feature = "rocksdb")))]
|
|
|
|
|
let db = serai_db::new_parity_db(path);
|
|
|
|
|
#[cfg(feature = "rocksdb")]
|
|
|
|
|
let db = serai_db::new_rocksdb(path);
|
|
|
|
|
db
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub(crate) fn coordinator_db() -> Db {
|
|
|
|
|
let root_path = serai_env::var("DB_PATH").expect("path to DB wasn't specified");
|
|
|
|
|
db(&format!("{root_path}/coordinator/db"))
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-30 03:14:24 -05:00
|
|
|
fn tributary_db_folder(set: ExternalValidatorSet) -> String {
|
2025-01-11 01:31:28 -05:00
|
|
|
let root_path = serai_env::var("DB_PATH").expect("path to DB wasn't specified");
|
|
|
|
|
let network = match set.network {
|
2025-01-30 03:14:24 -05:00
|
|
|
ExternalNetworkId::Bitcoin => "Bitcoin",
|
|
|
|
|
ExternalNetworkId::Ethereum => "Ethereum",
|
|
|
|
|
ExternalNetworkId::Monero => "Monero",
|
2025-01-11 01:31:28 -05:00
|
|
|
};
|
|
|
|
|
format!("{root_path}/tributary-{network}-{}", set.session.0)
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-30 03:14:24 -05:00
|
|
|
pub(crate) fn tributary_db(set: ExternalValidatorSet) -> Db {
|
2025-01-11 01:31:28 -05:00
|
|
|
db(&format!("{}/db", tributary_db_folder(set)))
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-30 03:14:24 -05:00
|
|
|
pub(crate) fn prune_tributary_db(set: ExternalValidatorSet) {
|
2025-01-11 01:31:28 -05:00
|
|
|
log::info!("pruning data directory for tributary {set:?}");
|
|
|
|
|
let db = tributary_db_folder(set);
|
|
|
|
|
if fs::exists(&db).expect("couldn't check if tributary DB exists") {
|
|
|
|
|
fs::remove_dir_all(db).unwrap();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
create_db! {
|
|
|
|
|
Coordinator {
|
2025-01-12 05:52:33 -05:00
|
|
|
// The currently active Tributaries
|
2025-01-11 01:31:28 -05:00
|
|
|
ActiveTributaries: () -> Vec<NewSetInformation>,
|
2025-01-12 05:52:33 -05:00
|
|
|
// The latest Tributary to have been retired for a network
|
|
|
|
|
// Since Tributaries are retired sequentially, this is informative to if any Tributary has been
|
|
|
|
|
// retired
|
2025-01-30 03:14:24 -05:00
|
|
|
RetiredTributary: (network: ExternalNetworkId) -> Session,
|
2025-01-12 05:52:33 -05:00
|
|
|
// The last handled message from a Processor
|
2025-01-30 03:14:24 -05:00
|
|
|
LastProcessorMessage: (network: ExternalNetworkId) -> u64,
|
2025-01-12 05:52:33 -05:00
|
|
|
// Cosigns we produced and tried to intake yet incurred an error while doing so
|
|
|
|
|
ErroneousCosigns: () -> Vec<SignedCosign>,
|
2025-01-15 20:29:57 -05:00
|
|
|
// The keys to confirm and set on the Serai network
|
2025-01-30 03:14:24 -05:00
|
|
|
KeysToConfirm: (set: ExternalValidatorSet) -> KeyPair,
|
2025-01-15 21:00:50 -05:00
|
|
|
// The key was set on the Serai network
|
2025-01-30 03:14:24 -05:00
|
|
|
KeySet: (set: ExternalValidatorSet) -> (),
|
2025-01-11 01:31:28 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
db_channel! {
|
|
|
|
|
Coordinator {
|
2025-01-12 05:52:33 -05:00
|
|
|
// Cosigns we produced
|
|
|
|
|
SignedCosigns: () -> SignedCosign,
|
2025-01-12 07:32:45 -05:00
|
|
|
// Tributaries to clean up upon reboot
|
2025-01-30 03:14:24 -05:00
|
|
|
TributaryCleanup: () -> ExternalValidatorSet,
|
2025-01-12 07:32:45 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mod _internal_db {
|
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
|
|
db_channel! {
|
|
|
|
|
Coordinator {
|
2025-01-15 20:29:57 -05:00
|
|
|
// Tributary transactions to publish from the Processor messages
|
2025-01-30 03:14:24 -05:00
|
|
|
TributaryTransactionsFromProcessorMessages: (set: ExternalValidatorSet) -> Transaction,
|
2025-01-15 20:29:57 -05:00
|
|
|
// Tributary transactions to publish from the DKG confirmation task
|
2025-01-30 03:14:24 -05:00
|
|
|
TributaryTransactionsFromDkgConfirmation: (set: ExternalValidatorSet) -> Transaction,
|
2025-01-15 12:51:35 -05:00
|
|
|
// Participants to remove
|
2025-11-16 11:50:24 -05:00
|
|
|
RemoveParticipant: (set: ExternalValidatorSet) -> u16,
|
2025-01-12 07:32:45 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-15 20:29:57 -05:00
|
|
|
pub(crate) struct TributaryTransactionsFromProcessorMessages;
|
|
|
|
|
impl TributaryTransactionsFromProcessorMessages {
|
2025-01-30 03:14:24 -05:00
|
|
|
pub(crate) fn send(txn: &mut impl DbTxn, set: ExternalValidatorSet, tx: &Transaction) {
|
2025-01-12 07:32:45 -05:00
|
|
|
// If this set has yet to be retired, send this transaction
|
|
|
|
|
if RetiredTributary::get(txn, set.network).map(|session| session.0) < Some(set.session.0) {
|
2025-01-15 20:29:57 -05:00
|
|
|
_internal_db::TributaryTransactionsFromProcessorMessages::send(txn, set, tx);
|
2025-01-12 07:32:45 -05:00
|
|
|
}
|
|
|
|
|
}
|
2025-01-30 03:14:24 -05:00
|
|
|
pub(crate) fn try_recv(txn: &mut impl DbTxn, set: ExternalValidatorSet) -> Option<Transaction> {
|
2025-01-15 20:29:57 -05:00
|
|
|
_internal_db::TributaryTransactionsFromProcessorMessages::try_recv(txn, set)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub(crate) struct TributaryTransactionsFromDkgConfirmation;
|
|
|
|
|
impl TributaryTransactionsFromDkgConfirmation {
|
2025-01-30 03:14:24 -05:00
|
|
|
pub(crate) fn send(txn: &mut impl DbTxn, set: ExternalValidatorSet, tx: &Transaction) {
|
2025-01-15 20:29:57 -05:00
|
|
|
// If this set has yet to be retired, send this transaction
|
|
|
|
|
if RetiredTributary::get(txn, set.network).map(|session| session.0) < Some(set.session.0) {
|
|
|
|
|
_internal_db::TributaryTransactionsFromDkgConfirmation::send(txn, set, tx);
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-01-30 03:14:24 -05:00
|
|
|
pub(crate) fn try_recv(txn: &mut impl DbTxn, set: ExternalValidatorSet) -> Option<Transaction> {
|
2025-01-15 20:29:57 -05:00
|
|
|
_internal_db::TributaryTransactionsFromDkgConfirmation::try_recv(txn, set)
|
2025-01-11 01:31:28 -05:00
|
|
|
}
|
|
|
|
|
}
|
2025-01-15 12:51:35 -05:00
|
|
|
|
|
|
|
|
pub(crate) struct RemoveParticipant;
|
|
|
|
|
impl RemoveParticipant {
|
2025-01-30 03:14:24 -05:00
|
|
|
pub(crate) fn send(txn: &mut impl DbTxn, set: ExternalValidatorSet, participant: Participant) {
|
2025-01-15 12:51:35 -05:00
|
|
|
// If this set has yet to be retired, send this transaction
|
|
|
|
|
if RetiredTributary::get(txn, set.network).map(|session| session.0) < Some(set.session.0) {
|
2025-11-16 11:50:24 -05:00
|
|
|
_internal_db::RemoveParticipant::send(txn, set, &u16::from(participant));
|
2025-01-15 12:51:35 -05:00
|
|
|
}
|
|
|
|
|
}
|
2025-01-30 03:14:24 -05:00
|
|
|
pub(crate) fn try_recv(txn: &mut impl DbTxn, set: ExternalValidatorSet) -> Option<Participant> {
|
2025-01-15 12:51:35 -05:00
|
|
|
_internal_db::RemoveParticipant::try_recv(txn, set)
|
2025-11-16 11:50:24 -05:00
|
|
|
.map(|i| Participant::new(i).expect("sent invalid participant index for removal"))
|
2025-01-15 12:51:35 -05:00
|
|
|
}
|
|
|
|
|
}
|