mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-08 20:29:23 +00:00
Clarify safety of Scanner::block_number and KeyGen::keys
This commit is contained in:
@@ -134,7 +134,11 @@ impl<C: Coin, D: Db> KeyGen<C, D> {
|
|||||||
key: &<C::Curve as Ciphersuite>::G,
|
key: &<C::Curve as Ciphersuite>::G,
|
||||||
) -> (ThresholdKeys<Ristretto>, ThresholdKeys<C::Curve>) {
|
) -> (ThresholdKeys<Ristretto>, ThresholdKeys<C::Curve>) {
|
||||||
// This is safe, despite not having a txn, since it's a static value
|
// This is safe, despite not having a txn, since it's a static value
|
||||||
// At worst, it's not set when it's expected to be set, yet that should be handled contextually
|
// The only concern is it may not be set when expected, or it may be set unexpectedly
|
||||||
|
// Since this unwraps, it being unset when expected to be set will cause a panic
|
||||||
|
// The only other concern is if it's set when it's not safe to use
|
||||||
|
// The keys are only written on confirmation, and the transaction writing them is atomic to
|
||||||
|
// every associated operation
|
||||||
KeyGenDb::<C, D>::keys(&self.db, key)
|
KeyGenDb::<C, D>::keys(&self.db, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -183,6 +183,7 @@ async fn sign_plans<C: Coin, D: Db>(
|
|||||||
|
|
||||||
let mut block_hash = <C::Block as Block<C>>::Id::default();
|
let mut block_hash = <C::Block as Block<C>>::Id::default();
|
||||||
block_hash.as_mut().copy_from_slice(&context.coin_latest_finalized_block.0);
|
block_hash.as_mut().copy_from_slice(&context.coin_latest_finalized_block.0);
|
||||||
|
// block_number call is safe since it unwraps
|
||||||
let block_number = substrate_mutable
|
let block_number = substrate_mutable
|
||||||
.scanner
|
.scanner
|
||||||
.block_number(&block_hash)
|
.block_number(&block_hash)
|
||||||
@@ -229,26 +230,26 @@ async fn handle_coordinator_msg<D: Db, C: Coin, Co: Coordinator>(
|
|||||||
let mut needed_hash = <C::Block as Block<C>>::Id::default();
|
let mut needed_hash = <C::Block as Block<C>>::Id::default();
|
||||||
needed_hash.as_mut().copy_from_slice(&block_hash.0);
|
needed_hash.as_mut().copy_from_slice(&block_hash.0);
|
||||||
|
|
||||||
let block_number;
|
let block_number = loop {
|
||||||
loop {
|
|
||||||
// Ensure our scanner has scanned this block, which means our daemon has this block at
|
// Ensure our scanner has scanned this block, which means our daemon has this block at
|
||||||
// a sufficient depth
|
// a sufficient depth
|
||||||
let Some(block_number_inner) = scanner.block_number(&needed_hash).await else {
|
// The block_number may be set even if scanning isn't complete
|
||||||
warn!(
|
let Some(block_number) = scanner.block_number(&needed_hash).await else {
|
||||||
"node is desynced. we haven't scanned {} which should happen after {} confirms",
|
warn!(
|
||||||
hex::encode(&needed_hash),
|
"node is desynced. we haven't scanned {} which should happen after {} confirms",
|
||||||
C::CONFIRMATIONS,
|
hex::encode(&needed_hash),
|
||||||
);
|
C::CONFIRMATIONS,
|
||||||
sleep(Duration::from_secs(10)).await;
|
);
|
||||||
continue;
|
sleep(Duration::from_secs(10)).await;
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
break block_number;
|
||||||
};
|
};
|
||||||
block_number = block_number_inner;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// While the scanner has cemented this block, that doesn't mean it's been scanned for all
|
// While the scanner has cemented this block, that doesn't mean it's been scanned for all
|
||||||
// keys
|
// keys
|
||||||
// ram_scanned will return the lowest scanned block number out of all keys
|
// ram_scanned will return the lowest scanned block number out of all keys
|
||||||
|
// This is a safe call which fulfills the unfulfilled safety requirements from the prior call
|
||||||
while scanner.ram_scanned().await < block_number {
|
while scanner.ram_scanned().await < block_number {
|
||||||
sleep(Duration::from_secs(1)).await;
|
sleep(Duration::from_secs(1)).await;
|
||||||
}
|
}
|
||||||
@@ -313,6 +314,7 @@ async fn handle_coordinator_msg<D: Db, C: Coin, Co: Coordinator>(
|
|||||||
|
|
||||||
let mut activation_block_hash = <C::Block as Block<C>>::Id::default();
|
let mut activation_block_hash = <C::Block as Block<C>>::Id::default();
|
||||||
activation_block_hash.as_mut().copy_from_slice(&activation_block.0);
|
activation_block_hash.as_mut().copy_from_slice(&activation_block.0);
|
||||||
|
// This block_number call is safe since it unwraps
|
||||||
let activation_number = substrate_mutable
|
let activation_number = substrate_mutable
|
||||||
.scanner
|
.scanner
|
||||||
.block_number(&activation_block_hash)
|
.block_number(&activation_block_hash)
|
||||||
|
|||||||
@@ -288,9 +288,10 @@ impl<C: Coin, D: Db> ScannerHandle<C, D> {
|
|||||||
scanner.keys.push(key);
|
scanner.keys.push(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This perform a database read which isn't safe with regards to if the value is set or not
|
||||||
|
// It may be set, when it isn't expected to be set, or not set, when it is expected to be set
|
||||||
|
// Since the value is static, if it's set, it's correctly set
|
||||||
pub async fn block_number(&self, id: &<C::Block as Block<C>>::Id) -> Option<usize> {
|
pub async fn block_number(&self, id: &<C::Block as Block<C>>::Id) -> Option<usize> {
|
||||||
// This is safe, despite not having a txn, since it's a static value
|
|
||||||
// At worst, it's not set when it's expected to be set, yet that should be handled contextually
|
|
||||||
ScannerDb::<C, D>::block_number(&self.scanner.read().await.db, id)
|
ScannerDb::<C, D>::block_number(&self.scanner.read().await.db, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -405,6 +406,9 @@ impl<C: Coin, D: Db> Scanner<C, D> {
|
|||||||
let block_id = block.id();
|
let block_id = block.id();
|
||||||
|
|
||||||
// These block calls are safe, despite not having a txn, since they're static values
|
// These block calls are safe, despite not having a txn, since they're static values
|
||||||
|
// only written to/read by this thread
|
||||||
|
// There's also no error caused by them being unexpectedly written (if the commit is
|
||||||
|
// made and then the processor suddenly reboots)
|
||||||
if let Some(id) = ScannerDb::<C, D>::block(&scanner.db, i) {
|
if let Some(id) = ScannerDb::<C, D>::block(&scanner.db, i) {
|
||||||
if id != block_id {
|
if id != block_id {
|
||||||
panic!("reorg'd from finalized {} to {}", hex::encode(id), hex::encode(block_id));
|
panic!("reorg'd from finalized {} to {}", hex::encode(id), hex::encode(block_id));
|
||||||
|
|||||||
Reference in New Issue
Block a user