mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-08 20:29:23 +00:00
Don't add transactions for topics which have yet to be recognized
This commit is contained in:
@@ -21,11 +21,19 @@ use message_queue::{Service, Metadata, client::MessageQueue};
|
|||||||
|
|
||||||
use serai_cosign::{Faulted, CosignIntent, Cosigning};
|
use serai_cosign::{Faulted, CosignIntent, Cosigning};
|
||||||
use serai_coordinator_substrate::{NewSetInformation, SignSlashReport};
|
use serai_coordinator_substrate::{NewSetInformation, SignSlashReport};
|
||||||
use serai_coordinator_tributary::{Transaction, ProcessorMessages, CosignIntents, ScanTributaryTask};
|
use serai_coordinator_tributary::{
|
||||||
|
Topic, Transaction, ProcessorMessages, CosignIntents, RecognizedTopics, ScanTributaryTask,
|
||||||
|
};
|
||||||
use serai_coordinator_p2p::P2p;
|
use serai_coordinator_p2p::P2p;
|
||||||
|
|
||||||
use crate::{Db, TributaryTransactions};
|
use crate::{Db, TributaryTransactions};
|
||||||
|
|
||||||
|
create_db! {
|
||||||
|
Coordinator {
|
||||||
|
PublishOnRecognition: (set: ValidatorSet, topic: Topic) -> Transaction,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
db_channel! {
|
db_channel! {
|
||||||
Coordinator {
|
Coordinator {
|
||||||
PendingCosigns: (set: ValidatorSet) -> CosignIntent,
|
PendingCosigns: (set: ValidatorSet) -> CosignIntent,
|
||||||
@@ -147,6 +155,37 @@ impl<CD: DbTrait, TD: DbTrait, P: P2p> ContinuallyRan
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
async fn add_signed_unsigned_transaction<TD: DbTrait, P: P2p>(
|
||||||
|
tributary: &Tributary<TD, Transaction, P>,
|
||||||
|
tx: &Transaction,
|
||||||
|
) -> bool {
|
||||||
|
let res = tributary.add_transaction(tx.clone()).await;
|
||||||
|
match &res {
|
||||||
|
// Fresh publication, already published
|
||||||
|
Ok(true | false) => {}
|
||||||
|
// InvalidNonce may be out-of-order TXs, not invalid ones, but we only create nonce #n+1 after
|
||||||
|
// on-chain inclusion of the TX with nonce #n, so it is invalid within our context
|
||||||
|
Err(
|
||||||
|
TransactionError::TooLargeTransaction |
|
||||||
|
TransactionError::InvalidSigner |
|
||||||
|
TransactionError::InvalidNonce |
|
||||||
|
TransactionError::InvalidSignature |
|
||||||
|
TransactionError::InvalidContent,
|
||||||
|
) => {
|
||||||
|
panic!("created an invalid transaction, tx: {tx:?}, err: {res:?}");
|
||||||
|
}
|
||||||
|
// We've published too many transactions recently
|
||||||
|
Err(TransactionError::TooManyInMempool) => {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// This isn't a Provided transaction so this should never be hit
|
||||||
|
Err(TransactionError::ProvidedAddedToMempool) => unreachable!(),
|
||||||
|
}
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
/// Adds all of the transactions sent via `TributaryTransactions`.
|
/// Adds all of the transactions sent via `TributaryTransactions`.
|
||||||
pub(crate) struct AddTributaryTransactionsTask<CD: DbTrait, TD: DbTrait, P: P2p> {
|
pub(crate) struct AddTributaryTransactionsTask<CD: DbTrait, TD: DbTrait, P: P2p> {
|
||||||
db: CD,
|
db: CD,
|
||||||
@@ -161,6 +200,8 @@ impl<CD: DbTrait, TD: DbTrait, P: P2p> ContinuallyRan for AddTributaryTransactio
|
|||||||
fn run_iteration(&mut self) -> impl Send + Future<Output = Result<bool, Self::Error>> {
|
fn run_iteration(&mut self) -> impl Send + Future<Output = Result<bool, Self::Error>> {
|
||||||
async move {
|
async move {
|
||||||
let mut made_progress = false;
|
let mut made_progress = false;
|
||||||
|
|
||||||
|
// Provide/add all transactions sent our way
|
||||||
loop {
|
loop {
|
||||||
let mut txn = self.db.txn();
|
let mut txn = self.db.txn();
|
||||||
let Some(mut tx) = TributaryTransactions::try_recv(&mut txn, self.set) else { break };
|
let Some(mut tx) = TributaryTransactions::try_recv(&mut txn, self.set) else { break };
|
||||||
@@ -174,29 +215,27 @@ impl<CD: DbTrait, TD: DbTrait, P: P2p> ContinuallyRan for AddTributaryTransactio
|
|||||||
tx.sign(&mut OsRng, self.tributary.genesis(), &self.key);
|
tx.sign(&mut OsRng, self.tributary.genesis(), &self.key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If this is a transaction with signing data, check the topic is recognized before
|
||||||
|
// publishing
|
||||||
|
let topic = tx.topic();
|
||||||
|
let still_requires_recognition = if let Some(topic) = topic {
|
||||||
|
(topic.requires_recognition() &&
|
||||||
|
(!RecognizedTopics::recognized(&self.tributary_db, self.set, topic)))
|
||||||
|
.then_some(topic)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
if let Some(topic) = still_requires_recognition {
|
||||||
|
// Queue the transaction until the topic is recognized
|
||||||
|
// We use the Tributary DB for this so it's cleaned up when the Tributary DB is
|
||||||
|
let mut txn = self.tributary_db.txn();
|
||||||
|
PublishOnRecognition::set(&mut txn, self.set, topic, &tx);
|
||||||
|
txn.commit();
|
||||||
|
} else {
|
||||||
// Actually add the transaction
|
// Actually add the transaction
|
||||||
// TODO: If this is a preprocess, make sure the topic has been recognized
|
if !add_signed_unsigned_transaction(&self.tributary, &tx).await {
|
||||||
let res = self.tributary.add_transaction(tx.clone()).await;
|
|
||||||
match &res {
|
|
||||||
// Fresh publication, already published
|
|
||||||
Ok(true | false) => {}
|
|
||||||
Err(
|
|
||||||
TransactionError::TooLargeTransaction |
|
|
||||||
TransactionError::InvalidSigner |
|
|
||||||
TransactionError::InvalidNonce |
|
|
||||||
TransactionError::InvalidSignature |
|
|
||||||
TransactionError::InvalidContent,
|
|
||||||
) => {
|
|
||||||
panic!("created an invalid transaction, tx: {tx:?}, err: {res:?}");
|
|
||||||
}
|
|
||||||
// We've published too many transactions recently
|
|
||||||
// Drop this txn to try to publish it again later on a future iteration
|
|
||||||
Err(TransactionError::TooManyInMempool) => {
|
|
||||||
drop(txn);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// This isn't a Provided transaction so this should never be hit
|
|
||||||
Err(TransactionError::ProvidedAddedToMempool) => unreachable!(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -204,6 +243,25 @@ impl<CD: DbTrait, TD: DbTrait, P: P2p> ContinuallyRan for AddTributaryTransactio
|
|||||||
made_progress = true;
|
made_progress = true;
|
||||||
txn.commit();
|
txn.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Provide/add all transactions due to newly recognized topics
|
||||||
|
loop {
|
||||||
|
let mut txn = self.tributary_db.txn();
|
||||||
|
let Some(topic) =
|
||||||
|
RecognizedTopics::try_recv_topic_requiring_recognition(&mut txn, self.set)
|
||||||
|
else {
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
if let Some(tx) = PublishOnRecognition::take(&mut txn, self.set, topic) {
|
||||||
|
if !add_signed_unsigned_transaction(&self.tributary, &tx).await {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
made_progress = true;
|
||||||
|
txn.commit();
|
||||||
|
}
|
||||||
|
|
||||||
Ok(made_progress)
|
Ok(made_progress)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,20 +15,35 @@ use crate::transaction::SigningProtocolRound;
|
|||||||
|
|
||||||
/// A topic within the database which the group participates in
|
/// A topic within the database which the group participates in
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Encode, BorshSerialize, BorshDeserialize)]
|
#[derive(Clone, Copy, PartialEq, Eq, Debug, Encode, BorshSerialize, BorshDeserialize)]
|
||||||
pub(crate) enum Topic {
|
pub enum Topic {
|
||||||
/// Vote to remove a participant
|
/// Vote to remove a participant
|
||||||
RemoveParticipant { participant: SeraiAddress },
|
RemoveParticipant {
|
||||||
|
/// The participant to remove
|
||||||
|
participant: SeraiAddress,
|
||||||
|
},
|
||||||
|
|
||||||
// DkgParticipation isn't represented here as participations are immediately sent to the
|
// DkgParticipation isn't represented here as participations are immediately sent to the
|
||||||
// processor, not accumulated within this databse
|
// processor, not accumulated within this databse
|
||||||
/// Participation in the signing protocol to confirm the DKG results on Substrate
|
/// Participation in the signing protocol to confirm the DKG results on Substrate
|
||||||
DkgConfirmation { attempt: u32, round: SigningProtocolRound },
|
DkgConfirmation {
|
||||||
|
/// The attempt number this is for
|
||||||
|
attempt: u32,
|
||||||
|
/// The round of the signing protocol
|
||||||
|
round: SigningProtocolRound,
|
||||||
|
},
|
||||||
|
|
||||||
/// The local view of the SlashReport, to be aggregated into the final SlashReport
|
/// The local view of the SlashReport, to be aggregated into the final SlashReport
|
||||||
SlashReport,
|
SlashReport,
|
||||||
|
|
||||||
/// Participation in a signing protocol
|
/// Participation in a signing protocol
|
||||||
Sign { id: VariantSignId, attempt: u32, round: SigningProtocolRound },
|
Sign {
|
||||||
|
/// The ID of the signing protocol
|
||||||
|
id: VariantSignId,
|
||||||
|
/// The attempt number this is for
|
||||||
|
attempt: u32,
|
||||||
|
/// The round of the signing protocol
|
||||||
|
round: SigningProtocolRound,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Participating {
|
enum Participating {
|
||||||
@@ -138,16 +153,17 @@ impl Topic {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn requires_whitelisting(&self) -> bool {
|
/// If this topic requires recognition before entries are permitted for it.
|
||||||
|
pub fn requires_recognition(&self) -> bool {
|
||||||
#[allow(clippy::match_same_arms)]
|
#[allow(clippy::match_same_arms)]
|
||||||
match self {
|
match self {
|
||||||
// We don't require whitelisting to remove a participant
|
// We don't require recognition to remove a participant
|
||||||
Topic::RemoveParticipant { .. } => false,
|
Topic::RemoveParticipant { .. } => false,
|
||||||
// We don't require whitelisting for the first attempt, solely the re-attempts
|
// We don't require recognition for the first attempt, solely the re-attempts
|
||||||
Topic::DkgConfirmation { attempt, .. } => *attempt != 0,
|
Topic::DkgConfirmation { attempt, .. } => *attempt != 0,
|
||||||
// We don't require whitelisting for the slash report
|
// We don't require recognition for the slash report
|
||||||
Topic::SlashReport { .. } => false,
|
Topic::SlashReport { .. } => false,
|
||||||
// We do require whitelisting for every sign protocol
|
// We do require recognition for every sign protocol
|
||||||
Topic::Sign { .. } => true,
|
Topic::Sign { .. } => true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -198,7 +214,7 @@ create_db!(
|
|||||||
// If this block has already been cosigned.
|
// If this block has already been cosigned.
|
||||||
Cosigned: (set: ValidatorSet, substrate_block_hash: [u8; 32]) -> (),
|
Cosigned: (set: ValidatorSet, substrate_block_hash: [u8; 32]) -> (),
|
||||||
|
|
||||||
// The plans to whitelist upon a `Transaction::SubstrateBlock` being included on-chain.
|
// The plans to recognize upon a `Transaction::SubstrateBlock` being included on-chain.
|
||||||
SubstrateBlockPlans: (set: ValidatorSet, substrate_block_hash: [u8; 32]) -> Vec<[u8; 32]>,
|
SubstrateBlockPlans: (set: ValidatorSet, substrate_block_hash: [u8; 32]) -> Vec<[u8; 32]>,
|
||||||
|
|
||||||
// The weight accumulated for a topic.
|
// The weight accumulated for a topic.
|
||||||
@@ -214,6 +230,7 @@ create_db!(
|
|||||||
db_channel!(
|
db_channel!(
|
||||||
CoordinatorTributary {
|
CoordinatorTributary {
|
||||||
ProcessorMessages: (set: ValidatorSet) -> messages::CoordinatorMessage,
|
ProcessorMessages: (set: ValidatorSet) -> messages::CoordinatorMessage,
|
||||||
|
RecognizedTopics: (set: ValidatorSet) -> Topic,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -262,7 +279,7 @@ impl TributaryDb {
|
|||||||
);
|
);
|
||||||
ActivelyCosigning::set(txn, set, &substrate_block_hash);
|
ActivelyCosigning::set(txn, set, &substrate_block_hash);
|
||||||
|
|
||||||
TributaryDb::recognize_topic(
|
Self::recognize_topic(
|
||||||
txn,
|
txn,
|
||||||
set,
|
set,
|
||||||
Topic::Sign {
|
Topic::Sign {
|
||||||
@@ -292,6 +309,10 @@ impl TributaryDb {
|
|||||||
|
|
||||||
pub(crate) fn recognize_topic(txn: &mut impl DbTxn, set: ValidatorSet, topic: Topic) {
|
pub(crate) fn recognize_topic(txn: &mut impl DbTxn, set: ValidatorSet, topic: Topic) {
|
||||||
AccumulatedWeight::set(txn, set, topic, &0);
|
AccumulatedWeight::set(txn, set, topic, &0);
|
||||||
|
RecognizedTopics::send(txn, set, &topic);
|
||||||
|
}
|
||||||
|
pub(crate) fn recognized(getter: &impl Get, set: ValidatorSet, topic: Topic) -> bool {
|
||||||
|
AccumulatedWeight::get(getter, set, topic).is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn start_of_block(txn: &mut impl DbTxn, set: ValidatorSet, block_number: u64) {
|
pub(crate) fn start_of_block(txn: &mut impl DbTxn, set: ValidatorSet, block_number: u64) {
|
||||||
@@ -350,8 +371,13 @@ impl TributaryDb {
|
|||||||
// nonces on transactions (deterministically to the topic)
|
// nonces on transactions (deterministically to the topic)
|
||||||
|
|
||||||
let accumulated_weight = AccumulatedWeight::get(txn, set, topic);
|
let accumulated_weight = AccumulatedWeight::get(txn, set, topic);
|
||||||
if topic.requires_whitelisting() && accumulated_weight.is_none() {
|
if topic.requires_recognition() && accumulated_weight.is_none() {
|
||||||
Self::fatal_slash(txn, set, validator, "participated in unrecognized topic");
|
Self::fatal_slash(
|
||||||
|
txn,
|
||||||
|
set,
|
||||||
|
validator,
|
||||||
|
"participated in unrecognized topic which requires recognition",
|
||||||
|
);
|
||||||
return DataSet::None;
|
return DataSet::None;
|
||||||
}
|
}
|
||||||
let mut accumulated_weight = accumulated_weight.unwrap_or(0);
|
let mut accumulated_weight = accumulated_weight.unwrap_or(0);
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ pub use transaction::{SigningProtocolRound, Signed, Transaction};
|
|||||||
|
|
||||||
mod db;
|
mod db;
|
||||||
use db::*;
|
use db::*;
|
||||||
|
pub use db::Topic;
|
||||||
|
|
||||||
/// Messages to send to the Processors.
|
/// Messages to send to the Processors.
|
||||||
pub struct ProcessorMessages;
|
pub struct ProcessorMessages;
|
||||||
@@ -62,10 +63,28 @@ impl CosignIntents {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The plans to whitelist upon a `Transaction::SubstrateBlock` being included on-chain.
|
/// An interface to the topics recognized on this Tributary.
|
||||||
|
pub struct RecognizedTopics;
|
||||||
|
impl RecognizedTopics {
|
||||||
|
/// If this topic has been recognized by this Tributary.
|
||||||
|
///
|
||||||
|
/// This will either be by explicit recognition or participation.
|
||||||
|
pub fn recognized(getter: &impl Get, set: ValidatorSet, topic: Topic) -> bool {
|
||||||
|
TributaryDb::recognized(getter, set, topic)
|
||||||
|
}
|
||||||
|
/// The next topic requiring recognition which has been recognized by this Tributary.
|
||||||
|
pub fn try_recv_topic_requiring_recognition(
|
||||||
|
txn: &mut impl DbTxn,
|
||||||
|
set: ValidatorSet,
|
||||||
|
) -> Option<Topic> {
|
||||||
|
db::RecognizedTopics::try_recv(txn, set)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The plans to recognize upon a `Transaction::SubstrateBlock` being included on-chain.
|
||||||
pub struct SubstrateBlockPlans;
|
pub struct SubstrateBlockPlans;
|
||||||
impl SubstrateBlockPlans {
|
impl SubstrateBlockPlans {
|
||||||
/// Set the plans to whitelist upon the associated `Transaction::SubstrateBlock` being included
|
/// Set the plans to recognize upon the associated `Transaction::SubstrateBlock` being included
|
||||||
/// on-chain.
|
/// on-chain.
|
||||||
///
|
///
|
||||||
/// This must be done before the associated `Transaction::Cosign` is provided.
|
/// This must be done before the associated `Transaction::Cosign` is provided.
|
||||||
@@ -75,7 +94,7 @@ impl SubstrateBlockPlans {
|
|||||||
substrate_block_hash: [u8; 32],
|
substrate_block_hash: [u8; 32],
|
||||||
plans: &Vec<[u8; 32]>,
|
plans: &Vec<[u8; 32]>,
|
||||||
) {
|
) {
|
||||||
db::SubstrateBlockPlans::set(txn, set, substrate_block_hash, &plans);
|
db::SubstrateBlockPlans::set(txn, set, substrate_block_hash, plans);
|
||||||
}
|
}
|
||||||
fn take(
|
fn take(
|
||||||
txn: &mut impl DbTxn,
|
txn: &mut impl DbTxn,
|
||||||
@@ -154,6 +173,7 @@ impl<'a, TD: Db, TDT: DbTxn, P: P2p> ScanBlock<'a, TD, TDT, P> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let topic = tx.topic();
|
||||||
match tx {
|
match tx {
|
||||||
// Accumulate this vote and fatally slash the participant if past the threshold
|
// Accumulate this vote and fatally slash the participant if past the threshold
|
||||||
Transaction::RemoveParticipant { participant, signed } => {
|
Transaction::RemoveParticipant { participant, signed } => {
|
||||||
@@ -176,7 +196,7 @@ impl<'a, TD: Db, TDT: DbTxn, P: P2p> ScanBlock<'a, TD, TDT, P> {
|
|||||||
self.validators,
|
self.validators,
|
||||||
self.total_weight,
|
self.total_weight,
|
||||||
block_number,
|
block_number,
|
||||||
Topic::RemoveParticipant { participant },
|
topic.unwrap(),
|
||||||
signer,
|
signer,
|
||||||
self.validator_weights[&signer],
|
self.validator_weights[&signer],
|
||||||
&(),
|
&(),
|
||||||
@@ -244,7 +264,7 @@ impl<'a, TD: Db, TDT: DbTxn, P: P2p> ScanBlock<'a, TD, TDT, P> {
|
|||||||
self.potentially_start_cosign();
|
self.potentially_start_cosign();
|
||||||
}
|
}
|
||||||
Transaction::SubstrateBlock { hash } => {
|
Transaction::SubstrateBlock { hash } => {
|
||||||
// Whitelist all of the IDs this Substrate block causes to be signed
|
// Recognize all of the IDs this Substrate block causes to be signed
|
||||||
let plans = SubstrateBlockPlans::take(self.tributary_txn, self.set, hash).expect(
|
let plans = SubstrateBlockPlans::take(self.tributary_txn, self.set, hash).expect(
|
||||||
"Transaction::SubstrateBlock locally provided but SubstrateBlockPlans wasn't populated",
|
"Transaction::SubstrateBlock locally provided but SubstrateBlockPlans wasn't populated",
|
||||||
);
|
);
|
||||||
@@ -261,7 +281,7 @@ impl<'a, TD: Db, TDT: DbTxn, P: P2p> ScanBlock<'a, TD, TDT, P> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Transaction::Batch { hash } => {
|
Transaction::Batch { hash } => {
|
||||||
// Whitelist the signing of this batch
|
// Recognize the signing of this batch
|
||||||
TributaryDb::recognize_topic(
|
TributaryDb::recognize_topic(
|
||||||
self.tributary_txn,
|
self.tributary_txn,
|
||||||
self.set,
|
self.set,
|
||||||
@@ -293,7 +313,7 @@ impl<'a, TD: Db, TDT: DbTxn, P: P2p> ScanBlock<'a, TD, TDT, P> {
|
|||||||
self.validators,
|
self.validators,
|
||||||
self.total_weight,
|
self.total_weight,
|
||||||
block_number,
|
block_number,
|
||||||
Topic::SlashReport,
|
topic.unwrap(),
|
||||||
signer,
|
signer,
|
||||||
self.validator_weights[&signer],
|
self.validator_weights[&signer],
|
||||||
&slash_points,
|
&slash_points,
|
||||||
@@ -351,7 +371,7 @@ impl<'a, TD: Db, TDT: DbTxn, P: P2p> ScanBlock<'a, TD, TDT, P> {
|
|||||||
|
|
||||||
// Create the resulting slash report
|
// Create the resulting slash report
|
||||||
let mut slash_report = vec![];
|
let mut slash_report = vec![];
|
||||||
for (validator, points) in self.validators.iter().copied().zip(amortized_slash_report) {
|
for (_, points) in self.validators.iter().copied().zip(amortized_slash_report) {
|
||||||
// TODO: Natively store this as a `Slash`
|
// TODO: Natively store this as a `Slash`
|
||||||
if points == u32::MAX {
|
if points == u32::MAX {
|
||||||
slash_report.push(Slash::Fatal);
|
slash_report.push(Slash::Fatal);
|
||||||
@@ -385,7 +405,7 @@ impl<'a, TD: Db, TDT: DbTxn, P: P2p> ScanBlock<'a, TD, TDT, P> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Transaction::Sign { id, attempt, round, data, signed } => {
|
Transaction::Sign { id, attempt, round, data, signed } => {
|
||||||
let topic = Topic::Sign { id, attempt, round };
|
let topic = topic.unwrap();
|
||||||
let signer = signer(signed);
|
let signer = signer(signed);
|
||||||
|
|
||||||
if u64::try_from(data.len()).unwrap() != self.validator_weights[&signer] {
|
if u64::try_from(data.len()).unwrap() != self.validator_weights[&signer] {
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ use tributary_sdk::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::db::Topic;
|
||||||
|
|
||||||
/// The round this data is for, within a signing protocol.
|
/// The round this data is for, within a signing protocol.
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Encode, BorshSerialize, BorshDeserialize)]
|
#[derive(Clone, Copy, PartialEq, Eq, Debug, Encode, BorshSerialize, BorshDeserialize)]
|
||||||
pub enum SigningProtocolRound {
|
pub enum SigningProtocolRound {
|
||||||
@@ -180,7 +182,7 @@ pub enum Transaction {
|
|||||||
///
|
///
|
||||||
/// This is provided after the block has been cosigned.
|
/// This is provided after the block has been cosigned.
|
||||||
///
|
///
|
||||||
/// With the acknowledgement of a Substrate block, we can whitelist all the `VariantSignId`s
|
/// With the acknowledgement of a Substrate block, we can recognize all the `VariantSignId`s
|
||||||
/// resulting from its handling.
|
/// resulting from its handling.
|
||||||
SubstrateBlock {
|
SubstrateBlock {
|
||||||
/// The hash of the Substrate block
|
/// The hash of the Substrate block
|
||||||
@@ -318,6 +320,36 @@ impl TransactionTrait for Transaction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Transaction {
|
impl Transaction {
|
||||||
|
/// The topic in the database for this transaction.
|
||||||
|
pub fn topic(&self) -> Option<Topic> {
|
||||||
|
#[allow(clippy::match_same_arms)] // This doesn't make semantic sense here
|
||||||
|
match self {
|
||||||
|
Transaction::RemoveParticipant { participant, .. } => {
|
||||||
|
Some(Topic::RemoveParticipant { participant: *participant })
|
||||||
|
}
|
||||||
|
|
||||||
|
Transaction::DkgParticipation { .. } => None,
|
||||||
|
Transaction::DkgConfirmationPreprocess { attempt, .. } => {
|
||||||
|
Some(Topic::DkgConfirmation { attempt: *attempt, round: SigningProtocolRound::Preprocess })
|
||||||
|
}
|
||||||
|
Transaction::DkgConfirmationShare { attempt, .. } => {
|
||||||
|
Some(Topic::DkgConfirmation { attempt: *attempt, round: SigningProtocolRound::Share })
|
||||||
|
}
|
||||||
|
|
||||||
|
// Provided TXs
|
||||||
|
Transaction::Cosign { .. } |
|
||||||
|
Transaction::Cosigned { .. } |
|
||||||
|
Transaction::SubstrateBlock { .. } |
|
||||||
|
Transaction::Batch { .. } => None,
|
||||||
|
|
||||||
|
Transaction::Sign { id, attempt, round, .. } => {
|
||||||
|
Some(Topic::Sign { id: *id, attempt: *attempt, round: *round })
|
||||||
|
}
|
||||||
|
|
||||||
|
Transaction::SlashReport { .. } => Some(Topic::SlashReport),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Sign a transaction.
|
/// Sign a transaction.
|
||||||
///
|
///
|
||||||
/// Panics if signing a transaction whose type isn't `TransactionKind::Signed`.
|
/// Panics if signing a transaction whose type isn't `TransactionKind::Signed`.
|
||||||
|
|||||||
Reference in New Issue
Block a user