mirror of
https://github.com/serai-dex/serai.git
synced 2025-02-02 03:06:31 +00:00
Call flush_key
This commit is contained in:
parent
8db76ed67c
commit
4f6d91037e
4 changed files with 68 additions and 23 deletions
|
@ -11,7 +11,8 @@ use serai_coins_primitives::OutInstructionWithBalance;
|
|||
use primitives::{EncodableG, Address, ReceivedOutput};
|
||||
|
||||
use crate::{
|
||||
lifetime::LifetimeStage, ScannerFeed, KeyFor, AddressFor, OutputFor, Return,
|
||||
lifetime::{LifetimeStage, Lifetime},
|
||||
ScannerFeed, KeyFor, AddressFor, OutputFor, Return,
|
||||
scan::next_to_scan_for_outputs_block,
|
||||
};
|
||||
|
||||
|
@ -30,6 +31,7 @@ pub(crate) struct SeraiKey<K> {
|
|||
pub(crate) stage: LifetimeStage,
|
||||
pub(crate) activation_block_number: u64,
|
||||
pub(crate) block_at_which_reporting_starts: u64,
|
||||
pub(crate) block_at_which_forwarding_starts: Option<u64>,
|
||||
}
|
||||
|
||||
pub(crate) struct OutputWithInInstruction<S: ScannerFeed> {
|
||||
|
@ -82,7 +84,7 @@ create_db!(
|
|||
/*
|
||||
A block is notable if one of three conditions are met:
|
||||
|
||||
1) We activated a key within this block.
|
||||
1) We activated a key within this block (or explicitly forward to an activated key).
|
||||
2) We retired a key within this block.
|
||||
3) We received outputs within this block.
|
||||
|
||||
|
@ -120,9 +122,32 @@ impl<S: ScannerFeed> ScannerGlobalDb<S> {
|
|||
|
||||
// TODO: Panic if we've ever seen this key before
|
||||
|
||||
// Push the key
|
||||
// Fetch the existing keys
|
||||
let mut keys: Vec<SeraiKeyDbEntry<EncodableG<KeyFor<S>>>> =
|
||||
ActiveKeys::get(txn).unwrap_or(vec![]);
|
||||
|
||||
// If this new key retires a key, mark the block at which forwarding explicitly occurs notable
|
||||
// This lets us obtain synchrony over the transactions we'll make to accomplish this
|
||||
if let Some(key_retired_by_this) = keys.last() {
|
||||
NotableBlock::set(
|
||||
txn,
|
||||
Lifetime::calculate::<S>(
|
||||
// The 'current block number' used for this calculation
|
||||
activation_block_number,
|
||||
// The activation block of the key we're getting the lifetime of
|
||||
key_retired_by_this.activation_block_number,
|
||||
// The activation block of the key which will retire this key
|
||||
Some(activation_block_number),
|
||||
)
|
||||
.block_at_which_forwarding_starts
|
||||
.expect(
|
||||
"didn't calculate the block forwarding starts at despite passing the next key's info",
|
||||
),
|
||||
&(),
|
||||
);
|
||||
}
|
||||
|
||||
// Push and save the next key
|
||||
keys.push(SeraiKeyDbEntry { activation_block_number, key: EncodableG(key) });
|
||||
ActiveKeys::set(txn, &keys);
|
||||
}
|
||||
|
@ -185,8 +210,8 @@ impl<S: ScannerFeed> ScannerGlobalDb<S> {
|
|||
if block_number < raw_keys[i].activation_block_number {
|
||||
continue;
|
||||
}
|
||||
let (stage, block_at_which_reporting_starts) =
|
||||
LifetimeStage::calculate_stage_and_reporting_start_block::<S>(
|
||||
let Lifetime { stage, block_at_which_reporting_starts, block_at_which_forwarding_starts } =
|
||||
Lifetime::calculate::<S>(
|
||||
block_number,
|
||||
raw_keys[i].activation_block_number,
|
||||
raw_keys.get(i + 1).map(|key| key.activation_block_number),
|
||||
|
@ -196,6 +221,7 @@ impl<S: ScannerFeed> ScannerGlobalDb<S> {
|
|||
stage,
|
||||
activation_block_number: raw_keys[i].activation_block_number,
|
||||
block_at_which_reporting_starts,
|
||||
block_at_which_forwarding_starts,
|
||||
});
|
||||
}
|
||||
assert!(keys.len() <= 2, "more than two keys active");
|
||||
|
|
|
@ -341,8 +341,15 @@ impl<D: Db, S: ScannerFeed, Sch: Scheduler<S>> ContinuallyRan for EventualityTas
|
|||
intake_eventualities::<S>(&mut txn, new_eventualities);
|
||||
}
|
||||
|
||||
// Now that we've intaked any Eventualities caused, check if we're retiring any keys
|
||||
for key in &keys {
|
||||
// If this is the block at which forwarding starts for this key, flush it
|
||||
// We do this after we issue the above update for any efficiencies gained by doing so
|
||||
if key.block_at_which_forwarding_starts == Some(b) {
|
||||
assert!(key.key != keys.last().unwrap().key);
|
||||
self.scheduler.flush_key(&mut txn, key.key, keys.last().unwrap().key);
|
||||
}
|
||||
|
||||
// Now that we've intaked any Eventualities caused, check if we're retiring any keys
|
||||
if key.stage == LifetimeStage::Finishing {
|
||||
let eventualities = EventualityDb::<S>::eventualities(&txn, key.key);
|
||||
// TODO: This assumes the Scheduler is empty
|
||||
|
|
|
@ -35,17 +35,25 @@ pub(crate) enum LifetimeStage {
|
|||
Finishing,
|
||||
}
|
||||
|
||||
impl LifetimeStage {
|
||||
/// Get the stage of its lifetime this multisig is in, and the block at which we start reporting
|
||||
/// outputs to it.
|
||||
/// The lifetime of the multisig, including various block numbers.
|
||||
pub(crate) struct Lifetime {
|
||||
pub(crate) stage: LifetimeStage,
|
||||
pub(crate) block_at_which_reporting_starts: u64,
|
||||
// This is only Some if the next key's activation block number is passed to calculate, and the
|
||||
// stage is at least `LifetimeStage::Active.`
|
||||
pub(crate) block_at_which_forwarding_starts: Option<u64>,
|
||||
}
|
||||
|
||||
impl Lifetime {
|
||||
/// Get the lifetime of this multisig.
|
||||
///
|
||||
/// Panics if the multisig being calculated for isn't actually active and a variety of other
|
||||
/// insane cases.
|
||||
pub(crate) fn calculate_stage_and_reporting_start_block<S: ScannerFeed>(
|
||||
pub(crate) fn calculate<S: ScannerFeed>(
|
||||
block_number: u64,
|
||||
activation_block_number: u64,
|
||||
next_keys_activation_block_number: Option<u64>,
|
||||
) -> (Self, u64) {
|
||||
) -> Self {
|
||||
assert!(
|
||||
activation_block_number >= block_number,
|
||||
"calculating lifetime stage for an inactive multisig"
|
||||
|
@ -55,14 +63,14 @@ impl LifetimeStage {
|
|||
let active_yet_not_reporting_end_block =
|
||||
activation_block_number + S::CONFIRMATIONS + S::TEN_MINUTES;
|
||||
// The exclusive end block is the inclusive start block
|
||||
let reporting_start_block = active_yet_not_reporting_end_block;
|
||||
let block_at_which_reporting_starts = active_yet_not_reporting_end_block;
|
||||
if block_number < active_yet_not_reporting_end_block {
|
||||
return (LifetimeStage::ActiveYetNotReporting, reporting_start_block);
|
||||
return Lifetime { stage: LifetimeStage::ActiveYetNotReporting, block_at_which_reporting_starts, block_at_which_forwarding_starts: None };
|
||||
}
|
||||
|
||||
let Some(next_keys_activation_block_number) = next_keys_activation_block_number else {
|
||||
// If there is no next multisig, this is the active multisig
|
||||
return (LifetimeStage::Active, reporting_start_block);
|
||||
return Lifetime { stage: LifetimeStage::Active, block_at_which_reporting_starts, block_at_which_forwarding_starts: None };
|
||||
};
|
||||
|
||||
assert!(
|
||||
|
@ -70,19 +78,22 @@ impl LifetimeStage {
|
|||
"next set of keys activated before this multisig activated"
|
||||
);
|
||||
|
||||
// If the new multisig is still having its activation block finalized on-chain, this multisig
|
||||
// is still active (step 3)
|
||||
let new_active_yet_not_reporting_end_block =
|
||||
next_keys_activation_block_number + S::CONFIRMATIONS + S::TEN_MINUTES;
|
||||
let new_active_and_used_for_change_end_block =
|
||||
new_active_yet_not_reporting_end_block + S::CONFIRMATIONS;
|
||||
// The exclusive end block is the inclusive start block
|
||||
let block_at_which_forwarding_starts = Some(new_active_and_used_for_change_end_block);
|
||||
|
||||
// If the new multisig is still having its activation block finalized on-chain, this multisig
|
||||
// is still active (step 3)
|
||||
if block_number < new_active_yet_not_reporting_end_block {
|
||||
return (LifetimeStage::Active, reporting_start_block);
|
||||
return Lifetime { stage: LifetimeStage::Active, block_at_which_reporting_starts, block_at_which_forwarding_starts };
|
||||
}
|
||||
|
||||
// Step 4 details a further CONFIRMATIONS
|
||||
let new_active_and_used_for_change_end_block =
|
||||
new_active_yet_not_reporting_end_block + S::CONFIRMATIONS;
|
||||
if block_number < new_active_and_used_for_change_end_block {
|
||||
return (LifetimeStage::UsingNewForChange, reporting_start_block);
|
||||
return Lifetime { stage: LifetimeStage::UsingNewForChange, block_at_which_reporting_starts, block_at_which_forwarding_starts };
|
||||
}
|
||||
|
||||
// Step 5 details a further 6 hours
|
||||
|
@ -90,10 +101,10 @@ impl LifetimeStage {
|
|||
let new_active_and_forwarded_to_end_block =
|
||||
new_active_and_used_for_change_end_block + (6 * 6 * S::TEN_MINUTES);
|
||||
if block_number < new_active_and_forwarded_to_end_block {
|
||||
return (LifetimeStage::Forwarding, reporting_start_block);
|
||||
return Lifetime { stage: LifetimeStage::Forwarding, block_at_which_reporting_starts, block_at_which_forwarding_starts };
|
||||
}
|
||||
|
||||
// Step 6
|
||||
(LifetimeStage::Finishing, reporting_start_block)
|
||||
Lifetime { stage: LifetimeStage::Finishing, block_at_which_reporting_starts, block_at_which_forwarding_starts }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -102,7 +102,8 @@ The following timeline is established:
|
|||
|
||||
5) For the next 6 hours, all non-`Branch` outputs received are immediately
|
||||
forwarded to the new multisig. Only external transactions to the new multisig
|
||||
are included in `Batch`s.
|
||||
are included in `Batch`s. Any outputs not yet transferred as change are
|
||||
explicitly transferred.
|
||||
|
||||
The new multisig infers the `InInstruction`, and refund address, for
|
||||
forwarded `External` outputs via reading what they were for the original
|
||||
|
|
Loading…
Reference in a new issue