Handle the combination of DKG removals with re-attempts

With a DKG removal comes a reduction in the amount of participants which was
ignored by re-attempts.

Now, we determine n/i based on the parties removed, and deterministically
obtain the context of who was removd.
This commit is contained in:
Luke Parker
2023-12-13 14:03:07 -05:00
parent 884b6a6fec
commit 77edd00725
15 changed files with 410 additions and 132 deletions

View File

@@ -1,3 +1,7 @@
use ciphersuite::{group::GroupEncoding, Ciphersuite, Ristretto};
use serai_client::validator_sets::primitives::ValidatorSet;
use tributary::{
ReadWrite,
transaction::{TransactionError, TransactionKind, Transaction as TransactionTrait},
@@ -20,6 +24,58 @@ 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 {
FatalSlashesAsOfDkgAttempt::get(getter, genesis, attempt).map(|keys| {
keys.iter().map(|key| <Ristretto as Ciphersuite>::G::from_bytes(key).unwrap()).collect()
})
}
}
pub fn latest_removed(getter: &impl Get, genesis: [u8; 32]) -> Vec<<Ristretto as Ciphersuite>::G> {
#[allow(clippy::unwrap_or_default)]
FatalSlashes::get(getter, genesis)
.unwrap_or(vec![])
.iter()
.map(|key| <Ristretto as Ciphersuite>::G::from_bytes(key).unwrap())
.collect()
}
pub fn removed_as_of_set_keys(
getter: &impl Get,
set: ValidatorSet,
genesis: [u8; 32],
) -> Option<Vec<<Ristretto as Ciphersuite>::G>> {
// SeraiDkgCompleted has the key placed on-chain.
// This key can be uniquely mapped to an attempt so long as one participant was honest, which we
// assume as a presumably honest participant.
// Resolve from generated key to attempt to fatally slashed as of attempt.
// This expect will trigger if this is prematurely called and Substrate has tracked the keys yet
// we haven't locally synced and handled the Tributary
// All callers of this, at the time of writing, ensure the Tributary has sufficiently synced
// making the panic with context more desirable than the None
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 fn removed_as_of_fatal_slash(
getter: &impl Get,
genesis: [u8; 32],
fatally_slashed: [u8; 32],
) -> Option<Vec<<Ristretto as Ciphersuite>::G>> {
FatalSlashesAsOfFatalSlash::get(getter, genesis, fatally_slashed).map(|keys| {
keys.iter().map(|key| <Ristretto as Ciphersuite>::G::from_bytes(key).unwrap()).collect()
})
}
pub async fn publish_signed_transaction<D: Db, P: crate::P2p>(
txn: &mut D::Transaction<'_>,
tributary: &Tributary<D, Transaction, P>,