Revert prior commit

An archive of all GlobalSessions is necessary to check for faults. The storage
cost is also minimal. While it should be avoided if it can be, it can't be
here.
This commit is contained in:
Luke Parker
2024-12-26 00:15:49 -05:00
parent f336ab1ece
commit cef5bc95b0
3 changed files with 40 additions and 54 deletions

View File

@@ -5,7 +5,7 @@ use serai_task::ContinuallyRan;
use crate::{ use crate::{
HasEvents, GlobalSession, NetworksLatestCosignedBlock, RequestNotableCosigns, HasEvents, GlobalSession, NetworksLatestCosignedBlock, RequestNotableCosigns,
intend::{GlobalSessions, BlockEventData, BlockEvents}, intend::{GlobalSessionsChannel, BlockEventData, BlockEvents},
}; };
create_db!( create_db!(
@@ -34,8 +34,8 @@ fn currently_evaluated_global_session_strict(
let existing = match CurrentlyEvaluatedGlobalSession::get(txn) { let existing = match CurrentlyEvaluatedGlobalSession::get(txn) {
Some(existing) => existing, Some(existing) => existing,
None => { None => {
let first = let first = GlobalSessionsChannel::try_recv(txn)
GlobalSessions::try_recv(txn).expect("fetching latest global session yet none declared"); .expect("fetching latest global session yet none declared");
CurrentlyEvaluatedGlobalSession::set(txn, &first); CurrentlyEvaluatedGlobalSession::set(txn, &first);
first first
} }
@@ -47,14 +47,14 @@ fn currently_evaluated_global_session_strict(
existing existing
}; };
if let Some(next) = GlobalSessions::peek(txn) { if let Some(next) = GlobalSessionsChannel::peek(txn) {
assert!( assert!(
block_number <= next.1.start_block_number, block_number <= next.1.start_block_number,
"currently_evaluated_global_session_strict wasn't called incrementally" "currently_evaluated_global_session_strict wasn't called incrementally"
); );
// If it's time for this session to activate, take it from the channel and set it // If it's time for this session to activate, take it from the channel and set it
if block_number == next.1.start_block_number { if block_number == next.1.start_block_number {
GlobalSessions::try_recv(txn).unwrap(); GlobalSessionsChannel::try_recv(txn).unwrap();
CurrentlyEvaluatedGlobalSession::set(txn, &next); CurrentlyEvaluatedGlobalSession::set(txn, &next);
res = next; res = next;
} }
@@ -63,23 +63,6 @@ fn currently_evaluated_global_session_strict(
res res
} }
// This is a non-strict function which won't panic, and also won't increment the session as needed.
pub(crate) fn currently_evaluated_global_session(
getter: &impl Get,
) -> Option<([u8; 32], GlobalSession)> {
// If there's a next session...
if let Some(next_global_session) = GlobalSessions::peek(getter) {
// and we've already evaluated the cosigns for the block declaring it...
if LatestCosignedBlockNumber::get(getter) == Some(next_global_session.1.start_block_number - 1)
{
// return it as the current session.
return Some(next_global_session);
}
}
// Else, return the current session
CurrentlyEvaluatedGlobalSession::get(getter)
}
/// A task to determine if a block has been cosigned and we should handle it. /// A task to determine if a block has been cosigned and we should handle it.
pub(crate) struct CosignEvaluatorTask<D: Db, R: RequestNotableCosigns> { pub(crate) struct CosignEvaluatorTask<D: Db, R: RequestNotableCosigns> {
pub(crate) db: D, pub(crate) db: D,

View File

@@ -26,7 +26,7 @@ pub(crate) struct BlockEventData {
db_channel! { db_channel! {
CosignIntendChannels { CosignIntendChannels {
GlobalSessions: () -> ([u8; 32], GlobalSession), GlobalSessionsChannel: () -> ([u8; 32], GlobalSession),
BlockEvents: () -> BlockEventData, BlockEvents: () -> BlockEventData,
IntendedCosigns: (set: ValidatorSet) -> CosignIntent, IntendedCosigns: (set: ValidatorSet) -> CosignIntent,
} }
@@ -128,14 +128,12 @@ impl<D: Db> ContinuallyRan for CosignIntendTask<D> {
stakes, stakes,
total_stake, total_stake,
}; };
if let Some((ending_global_session, _ending_global_session_info)) = global_session_for_this_block { GlobalSessions::set(&mut txn, global_session, &global_session_info);
if let Some(ending_global_session) = global_session_for_this_block {
GlobalSessionsLastBlock::set(&mut txn, ending_global_session, &block_number); GlobalSessionsLastBlock::set(&mut txn, ending_global_session, &block_number);
} }
LatestGlobalSessionIntended::set( LatestGlobalSessionIntended::set(&mut txn, &global_session);
&mut txn, GlobalSessionsChannel::send(&mut txn, &(global_session, global_session_info));
&(global_session, global_session_info.clone()),
);
GlobalSessions::send(&mut txn, &(global_session, global_session_info));
} }
// If there isn't anyone available to cosign this block, meaning it'll never be cosigned, // If there isn't anyone available to cosign this block, meaning it'll never be cosigned,
@@ -147,9 +145,10 @@ impl<D: Db> ContinuallyRan for CosignIntendTask<D> {
match has_events { match has_events {
HasEvents::Notable | HasEvents::NonNotable => { HasEvents::Notable | HasEvents::NonNotable => {
let (global_session_for_this_block, global_session_info) = let global_session_for_this_block = global_session_for_this_block
global_session_for_this_block
.expect("global session for this block was None but still attempting to cosign it"); .expect("global session for this block was None but still attempting to cosign it");
let global_session_info = GlobalSessions::get(&txn, global_session_for_this_block)
.expect("last global session intended wasn't saved to the database");
// Tell each set of their expectation to cosign this block // Tell each set of their expectation to cosign this block
for set in global_session_info.sets { for set in global_session_info.sets {

View File

@@ -45,7 +45,7 @@ pub const COSIGN_CONTEXT: &[u8] = b"serai-cosign";
have validator sets follow two distinct global sessions without breaking the bounds of the have validator sets follow two distinct global sessions without breaking the bounds of the
cosigning protocol. cosigning protocol.
*/ */
#[derive(Clone, Debug, BorshSerialize, BorshDeserialize)] #[derive(Debug, BorshSerialize, BorshDeserialize)]
pub(crate) struct GlobalSession { pub(crate) struct GlobalSession {
pub(crate) start_block_number: u64, pub(crate) start_block_number: u64,
pub(crate) sets: Vec<ValidatorSet>, pub(crate) sets: Vec<ValidatorSet>,
@@ -66,12 +66,14 @@ create_db! {
// An index of Substrate blocks // An index of Substrate blocks
SubstrateBlocks: (block_number: u64) -> [u8; 32], SubstrateBlocks: (block_number: u64) -> [u8; 32],
// A mapping from a global session's ID to its relevant information.
GlobalSessions: (global_session: [u8; 32]) -> GlobalSession,
// The last block to be cosigned by a global session. // The last block to be cosigned by a global session.
GlobalSessionsLastBlock: (global_session: [u8; 32]) -> u64, GlobalSessionsLastBlock: (global_session: [u8; 32]) -> u64,
// The latest global session intended. // The latest global session intended.
// //
// This is distinct from the latest global session for which we've evaluated the cosigns for. // This is distinct from the latest global session for which we've evaluated the cosigns for.
LatestGlobalSessionIntended: () -> ([u8; 32], GlobalSession), LatestGlobalSessionIntended: () -> [u8; 32],
// The following are managed by the `intake_cosign` function present in this file // The following are managed by the `intake_cosign` function present in this file
@@ -285,9 +287,7 @@ impl<D: Db> Cosigning<D> {
} }
cosigns cosigns
} else { } else {
let Some((latest_global_session, _latest_global_session_info)) = let Some(latest_global_session) = LatestGlobalSessionIntended::get(&self.db) else {
LatestGlobalSessionIntended::get(&self.db)
else {
return vec![]; return vec![];
}; };
let mut cosigns = Vec::with_capacity(serai_client::primitives::NETWORKS.len()); let mut cosigns = Vec::with_capacity(serai_client::primitives::NETWORKS.len());
@@ -320,6 +320,12 @@ impl<D: Db> Cosigning<D> {
let cosign = &signed_cosign.cosign; let cosign = &signed_cosign.cosign;
let network = cosign.cosigner; let network = cosign.cosigner;
// Check our indexed blockchain includes a block with this block number
let Some(our_block_hash) = SubstrateBlocks::get(&self.db, cosign.block_number) else {
return Ok(true);
};
let faulty = our_block_hash == cosign.block_hash;
// Check this isn't a dated cosign within its global session (as it would be if rebroadcasted) // Check this isn't a dated cosign within its global session (as it would be if rebroadcasted)
if let Some(existing) = if let Some(existing) =
NetworksLatestCosignedBlock::get(&self.db, cosign.global_session, network) NetworksLatestCosignedBlock::get(&self.db, cosign.global_session, network)
@@ -329,24 +335,13 @@ impl<D: Db> Cosigning<D> {
} }
} }
// Check our indexed blockchain includes a block with this block number let Some(global_session) = GlobalSessions::get(&self.db, cosign.global_session) else {
let Some(our_block_hash) = SubstrateBlocks::get(&self.db, cosign.block_number) else { // Unrecognized global session
return Ok(true); return Ok(true);
}; };
// Check the cosign aligns with the global session we're currently working on
let Some((global_session, global_session_info)) =
evaluator::currently_evaluated_global_session(&self.db)
else {
// We haven't recognized any global sessions yet
return Ok(true);
};
if cosign.global_session != global_session {
return Ok(true);
}
// Check the cosigned block number is in range to the global session // Check the cosigned block number is in range to the global session
if cosign.block_number < global_session_info.start_block_number { if cosign.block_number < global_session.start_block_number {
// Cosign is for a block predating the global session // Cosign is for a block predating the global session
return Ok(false); return Ok(false);
} }
@@ -360,7 +355,7 @@ impl<D: Db> Cosigning<D> {
// Check the cosign's signature // Check the cosign's signature
{ {
let key = Public::from({ let key = Public::from({
let Some(key) = global_session_info.keys.get(&network) else { let Some(key) = global_session.keys.get(&network) else {
return Ok(false); return Ok(false);
}; };
*key *key
@@ -377,6 +372,15 @@ impl<D: Db> Cosigning<D> {
let mut txn = self.db.txn(); let mut txn = self.db.txn();
if our_block_hash == cosign.block_hash { if our_block_hash == cosign.block_hash {
// If this is for a future global session, we don't acknowledge this cosign at this time
let latest_cosigned_block_number = LatestCosignedBlockNumber::get(&txn).unwrap_or(0);
// This global session starts the block *after* its declaration, so we want to check if the
// block declaring it was cosigned
if (global_session.start_block_number - 1) > latest_cosigned_block_number {
drop(txn);
return Ok(true);
}
NetworksLatestCosignedBlock::set(&mut txn, cosign.global_session, network, signed_cosign); NetworksLatestCosignedBlock::set(&mut txn, cosign.global_session, network, signed_cosign);
} else { } else {
let mut faults = Faults::get(&txn, cosign.global_session).unwrap_or(vec![]); let mut faults = Faults::get(&txn, cosign.global_session).unwrap_or(vec![]);
@@ -387,14 +391,14 @@ impl<D: Db> Cosigning<D> {
let mut weight_cosigned = 0; let mut weight_cosigned = 0;
for fault in &faults { for fault in &faults {
let Some(stake) = global_session_info.stakes.get(&fault.cosign.cosigner) else { let Some(stake) = global_session.stakes.get(&fault.cosign.cosigner) else {
Err("cosigner with recognized key didn't have a stake entry saved".to_string())? Err("cosigner with recognized key didn't have a stake entry saved".to_string())?
}; };
weight_cosigned += stake; weight_cosigned += stake;
} }
// Check if the sum weight means a fault has occurred // Check if the sum weight means a fault has occurred
if weight_cosigned >= ((global_session_info.total_stake * 17) / 100) { if weight_cosigned >= ((global_session.total_stake * 17) / 100) {
FaultedSession::set(&mut txn, &cosign.global_session); FaultedSession::set(&mut txn, &cosign.global_session);
} }
} }