use ciphersuite::{group::GroupEncoding, Ciphersuite, Ristretto};
use serai_client::validator_sets::primitives::ExternalValidatorSet;
use tributary::{
ReadWrite,
transaction::{TransactionError, TransactionKind, Transaction as TransactionTrait},
Tributary,
};
mod db;
pub use db::*;
mod spec;
pub use spec::TributarySpec;
mod transaction;
pub use transaction::{Label, SignData, Transaction};
mod signing_protocol;
mod handle;
pub use handle::*;
pub mod scanner;
pub fn removed_as_of_dkg_attempt(
getter: &impl Get,
genesis: [u8; 32],
attempt: u32,
) -> Option<Vec<<Ristretto as Ciphersuite>::G>> {
if attempt == 0 {
Some(vec![])
} else {
RemovedAsOfDkgAttempt::get(getter, genesis, attempt).map(|keys| {
keys.iter().map(|key| <Ristretto as Ciphersuite>::G::from_bytes(key).unwrap()).collect()
})
}
}
pub fn removed_as_of_set_keys(
getter: &impl Get,
set: ExternalValidatorSet,
genesis: [u8; 32],
) -> Option<Vec<<Ristretto as Ciphersuite>::G>> {
let attempt = KeyToDkgAttempt::get(getter, SeraiDkgCompleted::get(getter, set)?)
.expect("key completed on-chain didn't have an attempt related");
removed_as_of_dkg_attempt(getter, genesis, attempt)
}
pub async fn publish_signed_transaction<D: Db, P: crate::P2p>(
txn: &mut D::Transaction<'_>,
tributary: &Tributary<D, Transaction, P>,
tx: Transaction,
) {
log::debug!("publishing transaction {}", hex::encode(tx.hash()));
let (order, signer) = if let TransactionKind::Signed(order, signed) = tx.kind() {
let signer = signed.signer;
SignedTransactionDb::set(txn, &order, signed.nonce, &tx.serialize());
(order, signer)
} else {
panic!("non-signed transaction passed to publish_signed_transaction");
};
while let Some(tx) = SignedTransactionDb::take_signed_transaction(
txn,
&order,
tributary
.next_nonce(&signer, &order)
.await
.expect("we don't have a nonce, meaning we aren't a participant on this tributary"),
) {
match tributary.add_transaction(tx.clone()).await {
Ok(_) => {}
Err(TransactionError::InvalidNonce) => {
log::warn!("publishing TX {tx:?} returned InvalidNonce. was it already added?")
}
Err(e) => panic!("created an invalid transaction: {e:?}"),
}
}
}