mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-08 12:19:24 +00:00
Remove historical state access from Serai
Resolves https://github.com/serai-dex/serai/issues/694.
This commit is contained in:
@@ -4,11 +4,18 @@ use std::{sync::Arc, collections::HashMap};
|
||||
use blake2::{Digest, Blake2b256};
|
||||
|
||||
use serai_client_serai::{
|
||||
abi::primitives::{
|
||||
balance::Amount, validator_sets::ExternalValidatorSet, address::SeraiAddress,
|
||||
merkle::IncrementalUnbalancedMerkleTree,
|
||||
abi::{
|
||||
primitives::{
|
||||
network_id::{ExternalNetworkId, NetworkId},
|
||||
balance::Amount,
|
||||
crypto::Public,
|
||||
validator_sets::{Session, ExternalValidatorSet},
|
||||
address::SeraiAddress,
|
||||
merkle::IncrementalUnbalancedMerkleTree,
|
||||
},
|
||||
validator_sets::Event,
|
||||
},
|
||||
Serai,
|
||||
Serai, Events,
|
||||
};
|
||||
|
||||
use serai_db::*;
|
||||
@@ -16,10 +23,20 @@ use serai_task::ContinuallyRan;
|
||||
|
||||
use crate::*;
|
||||
|
||||
#[derive(BorshSerialize, BorshDeserialize)]
|
||||
struct Set {
|
||||
session: Session,
|
||||
key: Public,
|
||||
stake: Amount,
|
||||
}
|
||||
|
||||
create_db!(
|
||||
CosignIntend {
|
||||
ScanCosignFrom: () -> u64,
|
||||
BuildsUpon: () -> IncrementalUnbalancedMerkleTree,
|
||||
Stakes: (network: ExternalNetworkId, validator: SeraiAddress) -> Amount,
|
||||
Validators: (set: ExternalValidatorSet) -> Vec<SeraiAddress>,
|
||||
LatestSet: (network: ExternalNetworkId) -> Set,
|
||||
}
|
||||
);
|
||||
|
||||
@@ -40,23 +57,38 @@ db_channel! {
|
||||
async fn block_has_events_justifying_a_cosign(
|
||||
serai: &Serai,
|
||||
block_number: u64,
|
||||
) -> Result<(Block, HasEvents), String> {
|
||||
) -> Result<(Block, Events, HasEvents), String> {
|
||||
let block = serai
|
||||
.block_by_number(block_number)
|
||||
.await
|
||||
.map_err(|e| format!("{e:?}"))?
|
||||
.ok_or_else(|| "couldn't get block which should've been finalized".to_string())?;
|
||||
let serai = serai.as_of(block.header.hash()).await.map_err(|e| format!("{e:?}"))?;
|
||||
let events = serai.events(block.header.hash()).await.map_err(|e| format!("{e:?}"))?;
|
||||
|
||||
if !serai.validator_sets().set_keys_events().await.map_err(|e| format!("{e:?}"))?.is_empty() {
|
||||
return Ok((block, HasEvents::Notable));
|
||||
if events.validator_sets().set_keys_events().next().is_some() {
|
||||
return Ok((block, events, HasEvents::Notable));
|
||||
}
|
||||
|
||||
if !serai.coins().burn_with_instruction_events().await.map_err(|e| format!("{e:?}"))?.is_empty() {
|
||||
return Ok((block, HasEvents::NonNotable));
|
||||
if events.coins().burn_with_instruction_events().next().is_some() {
|
||||
return Ok((block, events, HasEvents::NonNotable));
|
||||
}
|
||||
|
||||
Ok((block, HasEvents::No))
|
||||
Ok((block, events, HasEvents::No))
|
||||
}
|
||||
|
||||
// Fetch the `ExternalValidatorSet`s, and their associated keys, used for cosigning as of this
|
||||
// block.
|
||||
fn cosigning_sets(getter: &impl Get) -> Vec<(ExternalValidatorSet, Public, Amount)> {
|
||||
let mut sets = vec![];
|
||||
for network in ExternalNetworkId::all() {
|
||||
let Some(Set { session, key, stake }) = LatestSet::get(getter, network) else {
|
||||
// If this network doesn't have usable keys, move on
|
||||
continue;
|
||||
};
|
||||
|
||||
sets.push((ExternalValidatorSet { network, session }, key, stake));
|
||||
}
|
||||
sets
|
||||
}
|
||||
|
||||
/// A task to determine which blocks we should intend to cosign.
|
||||
@@ -77,7 +109,7 @@ impl<D: Db> ContinuallyRan for CosignIntendTask<D> {
|
||||
for block_number in start_block_number ..= latest_block_number {
|
||||
let mut txn = self.db.txn();
|
||||
|
||||
let (block, mut has_events) =
|
||||
let (block, events, mut has_events) =
|
||||
block_has_events_justifying_a_cosign(&self.serai, block_number)
|
||||
.await
|
||||
.map_err(|e| format!("{e:?}"))?;
|
||||
@@ -105,32 +137,75 @@ impl<D: Db> ContinuallyRan for CosignIntendTask<D> {
|
||||
);
|
||||
BuildsUpon::set(&mut txn, &builds_upon);
|
||||
|
||||
// Update the stakes
|
||||
for event in events.validator_sets().allocation_events() {
|
||||
let Event::Allocation { validator, network, amount } = event else {
|
||||
panic!("event from `allocation_events` wasn't `Event::Allocation`")
|
||||
};
|
||||
let Ok(network) = ExternalNetworkId::try_from(*network) else { continue };
|
||||
let existing = Stakes::get(&txn, network, *validator).unwrap_or(Amount(0));
|
||||
Stakes::set(&mut txn, network, *validator, &Amount(existing.0 + amount.0));
|
||||
}
|
||||
for event in events.validator_sets().deallocation_events() {
|
||||
let Event::Deallocation { validator, network, amount, timeline: _ } = event else {
|
||||
panic!("event from `deallocation_events` wasn't `Event::Deallocation`")
|
||||
};
|
||||
let Ok(network) = ExternalNetworkId::try_from(*network) else { continue };
|
||||
let existing = Stakes::get(&txn, network, *validator).unwrap_or(Amount(0));
|
||||
Stakes::set(&mut txn, network, *validator, &Amount(existing.0 - amount.0));
|
||||
}
|
||||
|
||||
// Handle decided sets
|
||||
for event in events.validator_sets().set_decided_events() {
|
||||
let Event::SetDecided { set, validators } = event else {
|
||||
panic!("event from `set_decided_events` wasn't `Event::SetDecided`")
|
||||
};
|
||||
|
||||
let Ok(set) = ExternalValidatorSet::try_from(*set) else { continue };
|
||||
Validators::set(
|
||||
&mut txn,
|
||||
set,
|
||||
&validators.iter().map(|(validator, _key_shares)| *validator).collect(),
|
||||
);
|
||||
}
|
||||
|
||||
// Handle declarations of the latest set
|
||||
for event in events.validator_sets().set_keys_events() {
|
||||
let Event::SetKeys { set, key_pair } = event else {
|
||||
panic!("event from `set_keys_events` wasn't `Event::SetKeys`")
|
||||
};
|
||||
let mut stake = 0;
|
||||
for validator in
|
||||
Validators::take(&mut txn, *set).expect("set which wasn't decided set keys")
|
||||
{
|
||||
stake += Stakes::get(&txn, set.network, validator).unwrap_or(Amount(0)).0;
|
||||
}
|
||||
LatestSet::set(
|
||||
&mut txn,
|
||||
set.network,
|
||||
&Set { session: set.session, key: key_pair.0, stake: Amount(stake) },
|
||||
);
|
||||
}
|
||||
|
||||
let global_session_for_this_block = LatestGlobalSessionIntended::get(&txn);
|
||||
|
||||
// If this is notable, it creates a new global session, which we index into the database
|
||||
// now
|
||||
if has_events == HasEvents::Notable {
|
||||
let serai = self.serai.as_of(block_hash).await.map_err(|e| format!("{e:?}"))?;
|
||||
let sets_and_keys = cosigning_sets(&serai).await?;
|
||||
let global_session =
|
||||
GlobalSession::id(sets_and_keys.iter().map(|(set, _key)| *set).collect());
|
||||
let sets_and_keys_and_stakes = cosigning_sets(&txn);
|
||||
let global_session = GlobalSession::id(
|
||||
sets_and_keys_and_stakes.iter().map(|(set, _key, _stake)| *set).collect(),
|
||||
);
|
||||
|
||||
let mut sets = Vec::with_capacity(sets_and_keys.len());
|
||||
let mut keys = HashMap::with_capacity(sets_and_keys.len());
|
||||
let mut stakes = HashMap::with_capacity(sets_and_keys.len());
|
||||
let mut sets = Vec::with_capacity(sets_and_keys_and_stakes.len());
|
||||
let mut keys = HashMap::with_capacity(sets_and_keys_and_stakes.len());
|
||||
let mut stakes = HashMap::with_capacity(sets_and_keys_and_stakes.len());
|
||||
let mut total_stake = 0;
|
||||
for (set, key) in &sets_and_keys {
|
||||
sets.push(*set);
|
||||
keys.insert(set.network, SeraiAddress::from(*key));
|
||||
let stake = serai
|
||||
.validator_sets()
|
||||
.current_stake(set.network.into())
|
||||
.await
|
||||
.map_err(|e| format!("{e:?}"))?
|
||||
.unwrap_or(Amount(0))
|
||||
.0;
|
||||
stakes.insert(set.network, stake);
|
||||
total_stake += stake;
|
||||
for (set, key, stake) in sets_and_keys_and_stakes {
|
||||
sets.push(set);
|
||||
keys.insert(set.network, key);
|
||||
stakes.insert(set.network, stake.0);
|
||||
total_stake += stake.0;
|
||||
}
|
||||
if total_stake == 0 {
|
||||
Err(format!("cosigning sets for block #{block_number} had 0 stake in total"))?;
|
||||
|
||||
@@ -20,7 +20,7 @@ use serai_client_serai::{
|
||||
},
|
||||
Block,
|
||||
},
|
||||
Serai, TemporalSerai,
|
||||
Serai, State,
|
||||
};
|
||||
|
||||
use serai_db::*;
|
||||
@@ -59,7 +59,7 @@ use delay::LatestCosignedBlockNumber;
|
||||
pub(crate) struct GlobalSession {
|
||||
pub(crate) start_block_number: u64,
|
||||
pub(crate) sets: Vec<ExternalValidatorSet>,
|
||||
pub(crate) keys: HashMap<ExternalNetworkId, SeraiAddress>,
|
||||
pub(crate) keys: HashMap<ExternalNetworkId, Public>,
|
||||
pub(crate) stakes: HashMap<ExternalNetworkId, u64>,
|
||||
pub(crate) total_stake: u64,
|
||||
}
|
||||
@@ -121,60 +121,6 @@ create_db! {
|
||||
}
|
||||
}
|
||||
|
||||
/// Fetch the keys used for cosigning by a specific network.
|
||||
async fn keys_for_network(
|
||||
serai: &TemporalSerai<'_>,
|
||||
network: ExternalNetworkId,
|
||||
) -> Result<Option<(Session, KeyPair)>, String> {
|
||||
let Some(latest_session) =
|
||||
serai.validator_sets().current_session(network.into()).await.map_err(|e| format!("{e:?}"))?
|
||||
else {
|
||||
// If this network hasn't had a session declared, move on
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
// Get the keys for the latest session
|
||||
if let Some(keys) = serai
|
||||
.validator_sets()
|
||||
.keys(ExternalValidatorSet { network, session: latest_session })
|
||||
.await
|
||||
.map_err(|e| format!("{e:?}"))?
|
||||
{
|
||||
return Ok(Some((latest_session, keys)));
|
||||
}
|
||||
|
||||
// If the latest session has yet to set keys, use the prior session
|
||||
if let Some(prior_session) = latest_session.0.checked_sub(1).map(Session) {
|
||||
if let Some(keys) = serai
|
||||
.validator_sets()
|
||||
.keys(ExternalValidatorSet { network, session: prior_session })
|
||||
.await
|
||||
.map_err(|e| format!("{e:?}"))?
|
||||
{
|
||||
return Ok(Some((prior_session, keys)));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
/// Fetch the `ExternalValidatorSet`s, and their associated keys, used for cosigning as of this
|
||||
/// block.
|
||||
async fn cosigning_sets(
|
||||
serai: &TemporalSerai<'_>,
|
||||
) -> Result<Vec<(ExternalValidatorSet, Public)>, String> {
|
||||
let mut sets = vec![];
|
||||
for network in ExternalNetworkId::all() {
|
||||
let Some((session, keys)) = keys_for_network(serai, network).await? else {
|
||||
// If this network doesn't have usable keys, move on
|
||||
continue;
|
||||
};
|
||||
|
||||
sets.push((ExternalValidatorSet { network, session }, keys.0));
|
||||
}
|
||||
Ok(sets)
|
||||
}
|
||||
|
||||
/// An object usable to request notable cosigns for a block.
|
||||
pub trait RequestNotableCosigns: 'static + Send {
|
||||
/// The error type which may be encountered when requesting notable cosigns.
|
||||
@@ -379,13 +325,8 @@ impl<D: Db> Cosigning<D> {
|
||||
|
||||
// Check the cosign's signature
|
||||
{
|
||||
let key = Public::from({
|
||||
let Some(key) = global_session.keys.get(&network) else {
|
||||
Err(IntakeCosignError::NonParticipatingNetwork)?
|
||||
};
|
||||
*key
|
||||
});
|
||||
|
||||
let key =
|
||||
*global_session.keys.get(&network).ok_or(IntakeCosignError::NonParticipatingNetwork)?;
|
||||
if !signed_cosign.verify_signature(key) {
|
||||
Err(IntakeCosignError::InvalidSignature)?;
|
||||
}
|
||||
|
||||
@@ -60,8 +60,7 @@ impl Validators {
|
||||
|
||||
Besides, we can't connect to historical validators, only the current validators.
|
||||
*/
|
||||
let temporal_serai = serai.borrow().as_of_latest_finalized_block().await?;
|
||||
let temporal_serai = temporal_serai.validator_sets();
|
||||
let serai = serai.borrow().state().await?;
|
||||
|
||||
let mut session_changes = vec![];
|
||||
{
|
||||
@@ -70,9 +69,9 @@ impl Validators {
|
||||
let mut futures = FuturesUnordered::new();
|
||||
for network in ExternalNetworkId::all() {
|
||||
let sessions = sessions.borrow();
|
||||
let temporal_serai = temporal_serai.borrow();
|
||||
let serai = serai.borrow();
|
||||
futures.push(async move {
|
||||
let session = match temporal_serai.current_session(network.into()).await {
|
||||
let session = match serai.current_session(network.into()).await {
|
||||
Ok(Some(session)) => session,
|
||||
Ok(None) => return Ok(None),
|
||||
Err(e) => return Err(e),
|
||||
@@ -81,7 +80,7 @@ impl Validators {
|
||||
if sessions.get(&network) == Some(&session) {
|
||||
Ok(None)
|
||||
} else {
|
||||
match temporal_serai.current_validators(network.into()).await {
|
||||
match serai.current_validators(network.into()).await {
|
||||
Ok(Some(validators)) => Ok(Some((
|
||||
network,
|
||||
session,
|
||||
|
||||
@@ -50,7 +50,6 @@ fn tributary_db_folder(set: ExternalValidatorSet) -> String {
|
||||
ExternalNetworkId::Bitcoin => "Bitcoin",
|
||||
ExternalNetworkId::Ethereum => "Ethereum",
|
||||
ExternalNetworkId::Monero => "Monero",
|
||||
_ => panic!("unrecognized `ExternalNetworkId`"),
|
||||
};
|
||||
format!("{root_path}/tributary-{network}-{}", set.session.0)
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@ serai-client-serai = { path = "../../substrate/client/serai", default-features =
|
||||
log = { version = "0.4", default-features = false, features = ["std"] }
|
||||
|
||||
futures = { version = "0.3", default-features = false, features = ["std"] }
|
||||
tokio = { version = "1", default-features = false }
|
||||
|
||||
serai-db = { path = "../../common/db", version = "0.1.1" }
|
||||
serai-task = { path = "../../common/task", version = "0.1" }
|
||||
|
||||
@@ -73,21 +73,13 @@ impl<D: Db> ContinuallyRan for CanonicalEventStream<D> {
|
||||
}
|
||||
Err(serai_cosign::Faulted) => return Err("cosigning process faulted".to_string()),
|
||||
};
|
||||
let temporal_serai = serai.as_of(block_hash).await.map_err(|e| format!("{e}"))?;
|
||||
let temporal_serai_validators = temporal_serai.validator_sets();
|
||||
let temporal_serai_instructions = temporal_serai.in_instructions();
|
||||
let temporal_serai_coins = temporal_serai.coins();
|
||||
|
||||
let (block, set_keys_events, slash_report_events, batch_events, burn_events) =
|
||||
tokio::try_join!(
|
||||
serai.block(block_hash),
|
||||
temporal_serai_validators.set_keys_events(),
|
||||
temporal_serai_validators.slash_report_events(),
|
||||
temporal_serai_instructions.batch_events(),
|
||||
temporal_serai_coins.burn_with_instruction_events(),
|
||||
)
|
||||
.map_err(|e| format!("{e:?}"))?;
|
||||
let Some(block) = block else {
|
||||
let events = serai.events(block_hash).await.map_err(|e| format!("{e}"))?;
|
||||
let set_keys_events = events.validator_sets().set_keys_events().cloned().collect();
|
||||
let slash_report_events =
|
||||
events.validator_sets().slash_report_events().cloned().collect();
|
||||
let batch_events = events.in_instructions().batch_events().cloned().collect();
|
||||
let burn_events = events.coins().burn_with_instruction_events().cloned().collect();
|
||||
let Some(block) = serai.block(block_hash).await.map_err(|e| format!("{e:?}"))? else {
|
||||
Err(format!("Serai node didn't have cosigned block #{block_number}"))?
|
||||
};
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ use futures::stream::{StreamExt, FuturesOrdered};
|
||||
use serai_client_serai::{
|
||||
abi::primitives::{
|
||||
BlockHash,
|
||||
crypto::EmbeddedEllipticCurveKeys,
|
||||
crypto::EmbeddedEllipticCurveKeys as EmbeddedEllipticCurveKeysStruct,
|
||||
network_id::ExternalNetworkId,
|
||||
validator_sets::{KeyShares, ExternalValidatorSet},
|
||||
address::SeraiAddress,
|
||||
@@ -24,6 +24,10 @@ use crate::NewSetInformation;
|
||||
create_db!(
|
||||
CoordinatorSubstrateEphemeral {
|
||||
NextBlock: () -> u64,
|
||||
EmbeddedEllipticCurveKeys: (
|
||||
network: ExternalNetworkId,
|
||||
validator: SeraiAddress
|
||||
) -> EmbeddedEllipticCurveKeysStruct,
|
||||
}
|
||||
);
|
||||
|
||||
@@ -56,6 +60,7 @@ impl<D: Db> ContinuallyRan for EphemeralEventStream<D> {
|
||||
struct EphemeralEvents {
|
||||
block_hash: BlockHash,
|
||||
time: u64,
|
||||
embedded_elliptic_curve_keys_events: Vec<serai_client_serai::abi::validator_sets::Event>,
|
||||
set_decided_events: Vec<serai_client_serai::abi::validator_sets::Event>,
|
||||
accepted_handover_events: Vec<serai_client_serai::abi::validator_sets::Event>,
|
||||
}
|
||||
@@ -76,15 +81,17 @@ impl<D: Db> ContinuallyRan for EphemeralEventStream<D> {
|
||||
Err(serai_cosign::Faulted) => return Err("cosigning process faulted".to_string()),
|
||||
};
|
||||
|
||||
let temporal_serai = serai.as_of(block_hash).await.map_err(|e| format!("{e}"))?;
|
||||
let temporal_serai_validators = temporal_serai.validator_sets();
|
||||
let (block, set_decided_events, accepted_handover_events) = tokio::try_join!(
|
||||
serai.block(block_hash),
|
||||
temporal_serai_validators.set_decided_events(),
|
||||
temporal_serai_validators.accepted_handover_events(),
|
||||
)
|
||||
.map_err(|e| format!("{e:?}"))?;
|
||||
let Some(block) = block else {
|
||||
let events = serai.events(block_hash).await.map_err(|e| format!("{e}"))?;
|
||||
let embedded_elliptic_curve_keys_events = events
|
||||
.validator_sets()
|
||||
.set_embedded_elliptic_curve_keys_events()
|
||||
.cloned()
|
||||
.collect::<Vec<_>>();
|
||||
let set_decided_events =
|
||||
events.validator_sets().set_decided_events().cloned().collect::<Vec<_>>();
|
||||
let accepted_handover_events =
|
||||
events.validator_sets().accepted_handover_events().cloned().collect::<Vec<_>>();
|
||||
let Some(block) = serai.block(block_hash).await.map_err(|e| format!("{e:?}"))? else {
|
||||
Err(format!("Serai node didn't have cosigned block #{block_number}"))?
|
||||
};
|
||||
|
||||
@@ -92,7 +99,13 @@ impl<D: Db> ContinuallyRan for EphemeralEventStream<D> {
|
||||
let time = block.header.unix_time_in_millis() / 1000;
|
||||
Ok((
|
||||
block_number,
|
||||
EphemeralEvents { block_hash, time, set_decided_events, accepted_handover_events },
|
||||
EphemeralEvents {
|
||||
block_hash,
|
||||
time,
|
||||
embedded_elliptic_curve_keys_events,
|
||||
set_decided_events,
|
||||
accepted_handover_events,
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
@@ -123,30 +136,39 @@ impl<D: Db> ContinuallyRan for EphemeralEventStream<D> {
|
||||
|
||||
let mut txn = self.db.txn();
|
||||
|
||||
for event in block.embedded_elliptic_curve_keys_events {
|
||||
let serai_client_serai::abi::validator_sets::Event::SetEmbeddedEllipticCurveKeys {
|
||||
validator,
|
||||
keys,
|
||||
} = &event
|
||||
else {
|
||||
panic!(
|
||||
"{}: {event:?}",
|
||||
"`SetEmbeddedEllipticCurveKeys` event wasn't a `SetEmbeddedEllipticCurveKeys` event"
|
||||
);
|
||||
};
|
||||
|
||||
EmbeddedEllipticCurveKeys::set(&mut txn, keys.network(), *validator, keys);
|
||||
}
|
||||
|
||||
for set_decided in block.set_decided_events {
|
||||
let serai_client_serai::abi::validator_sets::Event::SetDecided { set, validators } =
|
||||
&set_decided
|
||||
else {
|
||||
panic!("`SetDecided` event wasn't a `SetDecided` event: {set_decided:?}");
|
||||
};
|
||||
|
||||
// We only coordinate over external networks
|
||||
let Ok(set) = ExternalValidatorSet::try_from(*set) else { continue };
|
||||
|
||||
let serai = self.serai.as_of(block.block_hash).await.map_err(|e| format!("{e}"))?;
|
||||
let serai = serai.validator_sets();
|
||||
let validators =
|
||||
validators.iter().map(|(validator, weight)| (*validator, weight)).collect::<Vec<_>>();
|
||||
validators.iter().map(|(validator, weight)| (*validator, weight.0)).collect::<Vec<_>>();
|
||||
|
||||
let in_set = validators.iter().any(|(validator, _)| *validator == self.validator);
|
||||
if in_set {
|
||||
if u16::try_from(validators.len()).is_err() {
|
||||
Err("more than u16::MAX validators sent")?;
|
||||
}
|
||||
|
||||
let validators = validators
|
||||
.into_iter()
|
||||
.map(|(validator, weight)| (validator, weight.0))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// Do the summation in u32 so we don't risk a u16 overflow
|
||||
let total_weight = validators.iter().map(|(_, weight)| u32::from(*weight)).sum::<u32>();
|
||||
if total_weight > u32::from(KeyShares::MAX_PER_SET) {
|
||||
@@ -159,50 +181,26 @@ impl<D: Db> ContinuallyRan for EphemeralEventStream<D> {
|
||||
.expect("value smaller than `u16` constant but doesn't fit in `u16`");
|
||||
|
||||
// Fetch all of the validators' embedded elliptic curve keys
|
||||
let mut embedded_elliptic_curve_keys = FuturesOrdered::new();
|
||||
for (validator, _) in &validators {
|
||||
let validator = *validator;
|
||||
// try_join doesn't return a future so we need to wrap it in this additional async
|
||||
// block
|
||||
embedded_elliptic_curve_keys.push_back({
|
||||
let serai = serai.clone();
|
||||
async move {
|
||||
match serai.embedded_elliptic_curve_keys(validator, set.network).await {
|
||||
Ok(Some(keys)) => Ok(Some((
|
||||
validator,
|
||||
match keys {
|
||||
EmbeddedEllipticCurveKeys::Bitcoin(substrate, external) => {
|
||||
assert_eq!(set.network, ExternalNetworkId::Bitcoin);
|
||||
(substrate, external.as_slice().to_vec())
|
||||
}
|
||||
EmbeddedEllipticCurveKeys::Ethereum(substrate, external) => {
|
||||
assert_eq!(set.network, ExternalNetworkId::Ethereum);
|
||||
(substrate, external.as_slice().to_vec())
|
||||
}
|
||||
EmbeddedEllipticCurveKeys::Monero(substrate) => {
|
||||
assert_eq!(set.network, ExternalNetworkId::Monero);
|
||||
(substrate, substrate.as_slice().to_vec())
|
||||
}
|
||||
},
|
||||
))),
|
||||
Ok(None) => Ok(None),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
let mut evrf_public_keys = Vec::with_capacity(usize::from(total_weight));
|
||||
for (validator, weight) in &validators {
|
||||
let Some((future_validator, (substrate_embedded_key, external_embedded_key))) =
|
||||
embedded_elliptic_curve_keys.next().await.unwrap().map_err(|e| format!("{e:?}"))?
|
||||
else {
|
||||
Err("`SetDecided` with validator missing an embedded key".to_string())?
|
||||
let keys = match EmbeddedEllipticCurveKeys::get(&txn, set.network, *validator)
|
||||
.expect("selected validator lacked embedded elliptic curve keys")
|
||||
{
|
||||
EmbeddedEllipticCurveKeysStruct::Bitcoin(substrate, external) => {
|
||||
assert_eq!(set.network, ExternalNetworkId::Bitcoin);
|
||||
(substrate, external.to_vec())
|
||||
}
|
||||
EmbeddedEllipticCurveKeysStruct::Ethereum(substrate, external) => {
|
||||
assert_eq!(set.network, ExternalNetworkId::Ethereum);
|
||||
(substrate, external.to_vec())
|
||||
}
|
||||
EmbeddedEllipticCurveKeysStruct::Monero(substrate) => {
|
||||
assert_eq!(set.network, ExternalNetworkId::Monero);
|
||||
(substrate, substrate.to_vec())
|
||||
}
|
||||
};
|
||||
assert_eq!(*validator, future_validator);
|
||||
|
||||
for _ in 0 .. *weight {
|
||||
evrf_public_keys.push((substrate_embedded_key, external_embedded_key.clone()));
|
||||
evrf_public_keys.push(keys.clone());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,6 +211,7 @@ impl<D: Db> ContinuallyRan for EphemeralEventStream<D> {
|
||||
// TODO: This should be inlined into the Processor's key gen code
|
||||
// It's legacy from when we removed participants from the key gen
|
||||
threshold: ((total_weight * 2) / 3) + 1,
|
||||
// TODO: Why are `validators` and `evrf_public_keys` two separate fields?
|
||||
validators,
|
||||
evrf_public_keys,
|
||||
participant_indexes: Default::default(),
|
||||
|
||||
@@ -36,8 +36,7 @@ impl<D: Db> PublishSlashReportTask<D> {
|
||||
|
||||
// This uses the latest finalized block, not the latest cosigned block, which should be
|
||||
// fine as in the worst case, the only impact is no longer attempting TX publication
|
||||
let serai = self.serai.as_of_latest_finalized_block().await.map_err(|e| format!("{e:?}"))?;
|
||||
let serai = serai.validator_sets();
|
||||
let serai = self.serai.state().await.map_err(|e| format!("{e:?}"))?;
|
||||
let session_after_slash_report = Session(session.0 + 1);
|
||||
let current_session =
|
||||
serai.current_session(network.into()).await.map_err(|e| format!("{e:?}"))?;
|
||||
|
||||
@@ -40,9 +40,7 @@ impl<D: Db> ContinuallyRan for SetKeysTask<D> {
|
||||
|
||||
// This uses the latest finalized block, not the latest cosigned block, which should be
|
||||
// fine as in the worst case, the only impact is no longer attempting TX publication
|
||||
let serai =
|
||||
self.serai.as_of_latest_finalized_block().await.map_err(|e| format!("{e:?}"))?;
|
||||
let serai = serai.validator_sets();
|
||||
let serai = self.serai.state().await.map_err(|e| format!("{e:?}"))?;
|
||||
let current_session =
|
||||
serai.current_session(network.into()).await.map_err(|e| format!("{e:?}"))?;
|
||||
let current_session = current_session.map(|session| session.0);
|
||||
|
||||
Reference in New Issue
Block a user