diff --git a/Cargo.lock b/Cargo.lock
index c8d00271..4d6bf218 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -6906,6 +6906,7 @@ dependencies = [
  "log",
  "parity-scale-codec",
  "serai-client",
+ "serai-cosign",
  "serai-db",
  "serai-env",
  "serai-message-queue",
@@ -7097,6 +7098,7 @@ dependencies = [
  "modular-frost",
  "parity-scale-codec",
  "rand_core",
+ "serai-cosign",
  "serai-db",
  "serai-in-instructions-primitives",
  "serai-primitives",
diff --git a/coordinator/cosign/src/lib.rs b/coordinator/cosign/src/lib.rs
index 517dd7f3..3d476c3d 100644
--- a/coordinator/cosign/src/lib.rs
+++ b/coordinator/cosign/src/lib.rs
@@ -104,6 +104,24 @@ pub struct Cosign {
   pub cosigner: NetworkId,
 }
 
+impl CosignIntent {
+  /// Convert this into a `Cosign`.
+  pub fn into_cosign(self, cosigner: NetworkId) -> Cosign {
+    let CosignIntent { global_session, block_number, block_hash, notable: _ } = self;
+    Cosign { global_session, block_number, block_hash, cosigner }
+  }
+}
+
+impl Cosign {
+  /// The message to sign to sign this cosign.
+  ///
+  /// This must be signed with schnorrkel, the context set to `COSIGN_CONTEXT`.
+  pub fn signature_message(&self) -> Vec<u8> {
+    // We use a schnorrkel context to domain-separate this
+    self.encode()
+  }
+}
+
 /// A signed cosign.
 #[derive(Clone, Debug, BorshSerialize, BorshDeserialize)]
 pub struct SignedCosign {
@@ -118,7 +136,7 @@ impl SignedCosign {
     let Ok(signer) = schnorrkel::PublicKey::from_bytes(&signer.0) else { return false };
     let Ok(signature) = schnorrkel::Signature::from_bytes(&self.signature) else { return false };
 
-    signer.verify_simple(COSIGN_CONTEXT, &self.cosign.encode(), &signature).is_ok()
+    signer.verify_simple(COSIGN_CONTEXT, &self.cosign.signature_message(), &signature).is_ok()
   }
 }
 
diff --git a/coordinator/tributary/src/transaction.rs b/coordinator/tributary/src/transaction.rs
index b302f8d7..d05bf3c2 100644
--- a/coordinator/tributary/src/transaction.rs
+++ b/coordinator/tributary/src/transaction.rs
@@ -365,10 +365,12 @@ impl Transaction {
         Transaction::DkgConfirmationPreprocess { ref mut signed, .. } => signed,
         Transaction::DkgConfirmationShare { ref mut signed, .. } => signed,
 
-        Transaction::Cosign { .. } => panic!("signing CosignSubstrateBlock"),
-        Transaction::Cosigned { .. } => panic!("signing Cosigned"),
-        Transaction::SubstrateBlock { .. } => panic!("signing SubstrateBlock"),
-        Transaction::Batch { .. } => panic!("signing Batch"),
+        Transaction::Cosign { .. } => panic!("signing Cosign transaction (provided)"),
+        Transaction::Cosigned { .. } => panic!("signing Cosigned transaction (provided)"),
+        Transaction::SubstrateBlock { .. } => {
+          panic!("signing SubstrateBlock transaction (provided)")
+        }
+        Transaction::Batch { .. } => panic!("signing Batch transaction (provided)"),
 
         Transaction::Sign { ref mut signed, .. } => signed,
 
diff --git a/processor/bin/Cargo.toml b/processor/bin/Cargo.toml
index 52ebaeb9..164036a0 100644
--- a/processor/bin/Cargo.toml
+++ b/processor/bin/Cargo.toml
@@ -28,6 +28,7 @@ ciphersuite = { path = "../../crypto/ciphersuite", default-features = false, fea
 dkg = { path = "../../crypto/dkg", default-features = false, features = ["std", "evrf-ristretto"] }
 
 serai-client = { path = "../../substrate/client", default-features = false }
+serai-cosign = { path = "../../coordinator/cosign" }
 
 log = { version = "0.4", default-features = false, features = ["std"] }
 env_logger = { version = "0.10", default-features = false, features = ["humantime"] }
diff --git a/processor/bin/src/coordinator.rs b/processor/bin/src/coordinator.rs
index 591826bd..62eb1097 100644
--- a/processor/bin/src/coordinator.rs
+++ b/processor/bin/src/coordinator.rs
@@ -3,12 +3,14 @@ use std::sync::{LazyLock, Arc, Mutex};
 
 use tokio::sync::mpsc;
 
-use scale::Encode;
 use serai_client::{
-  primitives::Signature, validator_sets::primitives::Session,
+  primitives::Signature,
+  validator_sets::primitives::{Session, SlashReport},
   in_instructions::primitives::SignedBatch,
 };
 
+use serai_cosign::SignedCosign;
+
 use serai_db::{Get, DbTxn, Db, create_db, db_channel};
 
 use scanner::ScannerFeed;
@@ -181,17 +183,11 @@ impl signers::Coordinator for CoordinatorSend {
 
   fn publish_cosign(
     &mut self,
-    block_number: u64,
-    block: [u8; 32],
-    signature: Signature,
+    cosign: SignedCosign,
   ) -> impl Send + Future<Output = Result<(), Self::EphemeralError>> {
     async move {
       self.send(&messages::ProcessorMessage::Coordinator(
-        messages::coordinator::ProcessorMessage::CosignedBlock {
-          block_number,
-          block,
-          signature: signature.encode(),
-        },
+        messages::coordinator::ProcessorMessage::CosignedBlock { cosign },
       ));
       Ok(())
     }
@@ -212,13 +208,15 @@ impl signers::Coordinator for CoordinatorSend {
   fn publish_slash_report_signature(
     &mut self,
     session: Session,
+    slash_report: SlashReport,
     signature: Signature,
   ) -> impl Send + Future<Output = Result<(), Self::EphemeralError>> {
     async move {
       self.send(&messages::ProcessorMessage::Coordinator(
         messages::coordinator::ProcessorMessage::SignedSlashReport {
           session,
-          signature: signature.encode(),
+          slash_report,
+          signature: signature.0,
         },
       ));
       Ok(())
diff --git a/processor/bin/src/lib.rs b/processor/bin/src/lib.rs
index 119c4f40..5109dcbc 100644
--- a/processor/bin/src/lib.rs
+++ b/processor/bin/src/lib.rs
@@ -221,20 +221,16 @@ pub async fn main_loop<
         signers.queue_message(txn, &msg)
       }
       messages::CoordinatorMessage::Coordinator(
-        messages::coordinator::CoordinatorMessage::CosignSubstrateBlock {
-          session,
-          block_number,
-          block,
-        },
+        messages::coordinator::CoordinatorMessage::CosignSubstrateBlock { session, cosign },
       ) => {
         let txn = txn.take().unwrap();
-        signers.cosign_block(txn, session, block_number, block)
+        signers.cosign_block(txn, session, &cosign)
       }
       messages::CoordinatorMessage::Coordinator(
-        messages::coordinator::CoordinatorMessage::SignSlashReport { session, report },
+        messages::coordinator::CoordinatorMessage::SignSlashReport { session, slash_report },
       ) => {
         let txn = txn.take().unwrap();
-        signers.sign_slash_report(txn, session, &report)
+        signers.sign_slash_report(txn, session, &slash_report)
       }
 
       messages::CoordinatorMessage::Substrate(msg) => match msg {
diff --git a/processor/messages/src/lib.rs b/processor/messages/src/lib.rs
index b8f496ab..7101fdc2 100644
--- a/processor/messages/src/lib.rs
+++ b/processor/messages/src/lib.rs
@@ -11,7 +11,7 @@ use validator_sets_primitives::{Session, KeyPair, SlashReport};
 use coins_primitives::OutInstructionWithBalance;
 use in_instructions_primitives::SignedBatch;
 
-use serai_cosign::{CosignIntent, SignedCosign};
+use serai_cosign::{Cosign, SignedCosign};
 
 #[derive(Clone, Copy, PartialEq, Eq, Debug, BorshSerialize, BorshDeserialize)]
 pub struct SubstrateContext {
@@ -166,7 +166,7 @@ pub mod coordinator {
     /// Cosign the specified Substrate block.
     ///
     /// This is sent by the Coordinator's Tributary scanner.
-    CosignSubstrateBlock { session: Session, intent: CosignIntent },
+    CosignSubstrateBlock { session: Session, cosign: Cosign },
     /// Sign the slash report for this session.
     ///
     /// This is sent by the Coordinator's Tributary scanner.
@@ -322,8 +322,8 @@ impl CoordinatorMessage {
       CoordinatorMessage::Coordinator(msg) => {
         let (sub, id) = match msg {
           // We only cosign a block once, and Reattempt is a separate message
-          coordinator::CoordinatorMessage::CosignSubstrateBlock { intent, .. } => {
-            (0, intent.block_number.encode())
+          coordinator::CoordinatorMessage::CosignSubstrateBlock { cosign, .. } => {
+            (0, cosign.block_number.encode())
           }
           // We only sign one slash report, and Reattempt is a separate message
           coordinator::CoordinatorMessage::SignSlashReport { session, .. } => (1, session.encode()),
diff --git a/processor/signers/Cargo.toml b/processor/signers/Cargo.toml
index ddd295d3..ecf588d4 100644
--- a/processor/signers/Cargo.toml
+++ b/processor/signers/Cargo.toml
@@ -40,6 +40,7 @@ serai-db = { path = "../../common/db" }
 log = { version = "0.4", default-features = false, features = ["std"] }
 tokio = { version = "1", default-features = false, features = ["rt-multi-thread", "sync", "time", "macros"] }
 
+serai-cosign = { path = "../../coordinator/cosign" }
 messages = { package = "serai-processor-messages", path = "../messages" }
 primitives = { package = "serai-processor-primitives", path = "../primitives" }
 scanner = { package = "serai-processor-scanner", path = "../scanner" }
diff --git a/processor/signers/src/batch/mod.rs b/processor/signers/src/batch/mod.rs
index 2c4fd1f5..f38666a8 100644
--- a/processor/signers/src/batch/mod.rs
+++ b/processor/signers/src/batch/mod.rs
@@ -69,7 +69,12 @@ impl<D: Db, E: GroupEncoding> BatchSignerTask<D, E> {
 
       let mut machines = Vec::with_capacity(keys.len());
       for keys in &keys {
-        machines.push(WrappedSchnorrkelMachine::new(keys.clone(), batch_message(&batch)));
+        // TODO: Fetch the context for this from a constant instead of re-defining it
+        machines.push(WrappedSchnorrkelMachine::new(
+          keys.clone(),
+          b"substrate",
+          batch_message(&batch),
+        ));
       }
       attempt_manager.register(VariantSignId::Batch(id), machines);
     }
@@ -106,7 +111,12 @@ impl<D: Db, E: Send + GroupEncoding> ContinuallyRan for BatchSignerTask<D, E> {
 
         let mut machines = Vec::with_capacity(self.keys.len());
         for keys in &self.keys {
-          machines.push(WrappedSchnorrkelMachine::new(keys.clone(), batch_message(&batch)));
+          // TODO: Also fetch the constant here
+          machines.push(WrappedSchnorrkelMachine::new(
+            keys.clone(),
+            b"substrate",
+            batch_message(&batch),
+          ));
         }
         for msg in self.attempt_manager.register(VariantSignId::Batch(batch_hash), machines) {
           BatchSignerToCoordinatorMessages::send(&mut txn, self.session, &msg);
diff --git a/processor/signers/src/coordinator/mod.rs b/processor/signers/src/coordinator/mod.rs
index 003c14cd..0fd10822 100644
--- a/processor/signers/src/coordinator/mod.rs
+++ b/processor/signers/src/coordinator/mod.rs
@@ -1,6 +1,7 @@
 use core::future::Future;
 
-use scale::Decode;
+use serai_primitives::Signature;
+
 use serai_db::{DbTxn, Db};
 
 use primitives::task::ContinuallyRan;
@@ -99,17 +100,11 @@ impl<D: Db, C: Coordinator> ContinuallyRan for CoordinatorTask<D, C> {
         // Publish the cosigns from this session
         {
           let mut txn = self.db.txn();
-          while let Some(((block_number, block_id), signature)) =
-            Cosign::try_recv(&mut txn, session)
-          {
+          while let Some(signed_cosign) = Cosign::try_recv(&mut txn, session) {
             iterated = true;
             self
               .coordinator
-              .publish_cosign(
-                block_number,
-                block_id,
-                <_>::decode(&mut signature.as_slice()).unwrap(),
-              )
+              .publish_cosign(signed_cosign)
               .await
               .map_err(|e| format!("couldn't publish Cosign: {e:?}"))?;
           }
@@ -119,15 +114,12 @@ impl<D: Db, C: Coordinator> ContinuallyRan for CoordinatorTask<D, C> {
         // If this session signed its slash report, publish its signature
         {
           let mut txn = self.db.txn();
-          if let Some(slash_report_signature) = SlashReportSignature::try_recv(&mut txn, session) {
+          if let Some((slash_report, signature)) = SignedSlashReport::try_recv(&mut txn, session) {
             iterated = true;
 
             self
               .coordinator
-              .publish_slash_report_signature(
-                session,
-                <_>::decode(&mut slash_report_signature.as_slice()).unwrap(),
-              )
+              .publish_slash_report_signature(session, slash_report, Signature(signature))
               .await
               .map_err(|e| {
                 format!("couldn't send slash report signature to the coordinator: {e:?}")
diff --git a/processor/signers/src/cosign/mod.rs b/processor/signers/src/cosign/mod.rs
index dc5de6cd..ddf6c490 100644
--- a/processor/signers/src/cosign/mod.rs
+++ b/processor/signers/src/cosign/mod.rs
@@ -9,7 +9,8 @@ use serai_validator_sets_primitives::Session;
 
 use serai_db::{DbTxn, Db};
 
-use messages::{sign::VariantSignId, coordinator::cosign_block_msg};
+use serai_cosign::{COSIGN_CONTEXT, Cosign as CosignStruct, SignedCosign};
+use messages::sign::VariantSignId;
 
 use primitives::task::{DoesNotError, ContinuallyRan};
 
@@ -34,7 +35,7 @@ pub(crate) struct CosignerTask<D: Db> {
   session: Session,
   keys: Vec<ThresholdKeys<Ristretto>>,
 
-  current_cosign: Option<(u64, [u8; 32])>,
+  current_cosign: Option<CosignStruct>,
   attempt_manager: AttemptManager<D, WrappedSchnorrkelMachine>,
 }
 
@@ -62,26 +63,34 @@ impl<D: Db> ContinuallyRan for CosignerTask<D> {
         let mut txn = self.db.txn();
         if let Some(cosign) = ToCosign::get(&txn, self.session) {
           // If this wasn't already signed for...
-          if LatestCosigned::get(&txn, self.session) < Some(cosign.0) {
+          if LatestCosigned::get(&txn, self.session) < Some(cosign.block_number) {
             // If this isn't the cosign we're currently working on, meaning it's fresh
-            if self.current_cosign != Some(cosign) {
+            if self.current_cosign.as_ref() != Some(&cosign) {
               // Retire the current cosign
-              if let Some(current_cosign) = self.current_cosign {
-                assert!(current_cosign.0 < cosign.0);
-                self.attempt_manager.retire(&mut txn, VariantSignId::Cosign(current_cosign.0));
+              if let Some(current_cosign) = &self.current_cosign {
+                assert!(current_cosign.block_number < cosign.block_number);
+                self
+                  .attempt_manager
+                  .retire(&mut txn, VariantSignId::Cosign(current_cosign.block_number));
               }
 
               // Set the cosign being worked on
-              self.current_cosign = Some(cosign);
+              self.current_cosign = Some(cosign.clone());
 
               let mut machines = Vec::with_capacity(self.keys.len());
               {
-                let message = cosign_block_msg(cosign.0, cosign.1);
+                let message = cosign.signature_message();
                 for keys in &self.keys {
-                  machines.push(WrappedSchnorrkelMachine::new(keys.clone(), message.clone()));
+                  machines.push(WrappedSchnorrkelMachine::new(
+                    keys.clone(),
+                    COSIGN_CONTEXT,
+                    message.clone(),
+                  ));
                 }
               }
-              for msg in self.attempt_manager.register(VariantSignId::Cosign(cosign.0), machines) {
+              for msg in
+                self.attempt_manager.register(VariantSignId::Cosign(cosign.block_number), machines)
+              {
                 CosignerToCoordinatorMessages::send(&mut txn, self.session, &msg);
               }
 
@@ -109,12 +118,19 @@ impl<D: Db> ContinuallyRan for CosignerTask<D> {
             let VariantSignId::Cosign(block_number) = id else {
               panic!("CosignerTask signed a non-Cosign")
             };
-            assert_eq!(Some(block_number), self.current_cosign.map(|cosign| cosign.0));
+            assert_eq!(
+              Some(block_number),
+              self.current_cosign.as_ref().map(|cosign| cosign.block_number)
+            );
 
             let cosign = self.current_cosign.take().unwrap();
-            LatestCosigned::set(&mut txn, self.session, &cosign.0);
+            LatestCosigned::set(&mut txn, self.session, &cosign.block_number);
+            let cosign = SignedCosign {
+              cosign,
+              signature: Signature::from(signature).encode().try_into().unwrap(),
+            };
             // Send the cosign
-            Cosign::send(&mut txn, self.session, &(cosign, Signature::from(signature).encode()));
+            Cosign::send(&mut txn, self.session, &cosign);
           }
         }
 
diff --git a/processor/signers/src/db.rs b/processor/signers/src/db.rs
index 2c13ddba..23862236 100644
--- a/processor/signers/src/db.rs
+++ b/processor/signers/src/db.rs
@@ -1,7 +1,9 @@
-use serai_validator_sets_primitives::{Session, Slash};
+use serai_validator_sets_primitives::{Session, SlashReport as SlashReportStruct};
 
 use serai_db::{Get, DbTxn, create_db, db_channel};
 
+use serai_cosign::{Cosign as CosignStruct, SignedCosign};
+
 use messages::sign::{ProcessorMessage, CoordinatorMessage};
 
 create_db! {
@@ -11,16 +13,16 @@ create_db! {
     LatestRetiredSession: () -> Session,
     ToCleanup: () -> Vec<(Session, Vec<u8>)>,
 
-    ToCosign: (session: Session) -> (u64, [u8; 32]),
+    ToCosign: (session: Session) -> CosignStruct,
   }
 }
 
 db_channel! {
   SignersGlobal {
-    Cosign: (session: Session) -> ((u64, [u8; 32]), Vec<u8>),
+    Cosign: (session: Session) -> SignedCosign,
 
-    SlashReport: (session: Session) -> Vec<Slash>,
-    SlashReportSignature: (session: Session) -> Vec<u8>,
+    SlashReport: (session: Session) -> SlashReportStruct,
+    SignedSlashReport: (session: Session) -> (SlashReportStruct, [u8; 64]),
 
     /*
       TODO: Most of these are pointless? We drop all active signing sessions on reboot. It's
diff --git a/processor/signers/src/lib.rs b/processor/signers/src/lib.rs
index 116f7b9e..2f5a4a04 100644
--- a/processor/signers/src/lib.rs
+++ b/processor/signers/src/lib.rs
@@ -11,11 +11,13 @@ use ciphersuite::{group::GroupEncoding, Ciphersuite, Ristretto};
 use frost::dkg::{ThresholdCore, ThresholdKeys};
 
 use serai_primitives::Signature;
-use serai_validator_sets_primitives::{Session, Slash};
+use serai_validator_sets_primitives::{Session, SlashReport};
 use serai_in_instructions_primitives::SignedBatch;
 
 use serai_db::{DbTxn, Db};
 
+use serai_cosign::{Cosign, SignedCosign};
+
 use messages::sign::{VariantSignId, ProcessorMessage, CoordinatorMessage};
 
 use primitives::task::{Task, TaskHandle, ContinuallyRan};
@@ -59,9 +61,7 @@ pub trait Coordinator: 'static + Send + Sync {
   /// Publish a cosign.
   fn publish_cosign(
     &mut self,
-    block_number: u64,
-    block_id: [u8; 32],
-    signature: Signature,
+    signed_cosign: SignedCosign,
   ) -> impl Send + Future<Output = Result<(), Self::EphemeralError>>;
 
   /// Publish a `SignedBatch`.
@@ -74,6 +74,7 @@ pub trait Coordinator: 'static + Send + Sync {
   fn publish_slash_report_signature(
     &mut self,
     session: Session,
+    slash_report: SlashReport,
     signature: Signature,
   ) -> impl Send + Future<Output = Result<(), Self::EphemeralError>>;
 }
@@ -408,19 +409,13 @@ impl<
   /// Cosign a block.
   ///
   /// This is a cheap call and able to be done inline from a higher-level loop.
-  pub fn cosign_block(
-    &mut self,
-    mut txn: impl DbTxn,
-    session: Session,
-    block_number: u64,
-    block: [u8; 32],
-  ) {
+  pub fn cosign_block(&mut self, mut txn: impl DbTxn, session: Session, cosign: &Cosign) {
     // Don't cosign blocks with already retired keys
     if Some(session.0) <= db::LatestRetiredSession::get(&txn).map(|session| session.0) {
       return;
     }
 
-    db::ToCosign::set(&mut txn, session, &(block_number, block));
+    db::ToCosign::set(&mut txn, session, cosign);
     txn.commit();
 
     if let Some(tasks) = self.tasks.get(&session) {
@@ -435,7 +430,7 @@ impl<
     &mut self,
     mut txn: impl DbTxn,
     session: Session,
-    slash_report: &Vec<Slash>,
+    slash_report: &SlashReport,
   ) {
     // Don't sign slash reports with already retired keys
     if Some(session.0) <= db::LatestRetiredSession::get(&txn).map(|session| session.0) {
diff --git a/processor/signers/src/slash_report.rs b/processor/signers/src/slash_report.rs
index a5d155ef..14437a74 100644
--- a/processor/signers/src/slash_report.rs
+++ b/processor/signers/src/slash_report.rs
@@ -3,11 +3,8 @@ use core::{marker::PhantomData, future::Future};
 use ciphersuite::Ristretto;
 use frost::dkg::ThresholdKeys;
 
-use scale::Encode;
 use serai_primitives::Signature;
-use serai_validator_sets_primitives::{
-  Session, ValidatorSet, SlashReport as SlashReportStruct, report_slashes_message,
-};
+use serai_validator_sets_primitives::Session;
 
 use serai_db::{DbTxn, Db};
 
@@ -20,7 +17,7 @@ use frost_attempt_manager::*;
 
 use crate::{
   db::{
-    SlashReport, SlashReportSignature, CoordinatorToSlashReportSignerMessages,
+    SlashReport, SignedSlashReport, CoordinatorToSlashReportSignerMessages,
     SlashReportSignerToCoordinatorMessages,
   },
   WrappedSchnorrkelMachine,
@@ -72,12 +69,14 @@ impl<D: Db, S: ScannerFeed> ContinuallyRan for SlashReportSignerTask<D, S> {
 
         let mut machines = Vec::with_capacity(self.keys.len());
         {
-          let message = report_slashes_message(
-            &ValidatorSet { network: S::NETWORK, session: self.session },
-            &SlashReportStruct(slash_report.try_into().unwrap()),
-          );
+          let message = slash_report.report_slashes_message();
           for keys in &self.keys {
-            machines.push(WrappedSchnorrkelMachine::new(keys.clone(), message.clone()));
+            // TODO: Fetch this constant from somewhere instead of inlining it
+            machines.push(WrappedSchnorrkelMachine::new(
+              keys.clone(),
+              b"substrate",
+              message.clone(),
+            ));
           }
         }
         let mut txn = self.db.txn();
@@ -105,12 +104,12 @@ impl<D: Db, S: ScannerFeed> ContinuallyRan for SlashReportSignerTask<D, S> {
           Response::Signature { id, signature } => {
             assert_eq!(id, VariantSignId::SlashReport);
             // Drain the channel
-            SlashReport::try_recv(&mut txn, self.session).unwrap();
+            let slash_report = SlashReport::try_recv(&mut txn, self.session).unwrap();
             // Send the signature
-            SlashReportSignature::send(
+            SignedSlashReport::send(
               &mut txn,
               self.session,
-              &Signature::from(signature).encode(),
+              &(slash_report, Signature::from(signature).0),
             );
           }
         }
diff --git a/processor/signers/src/wrapped_schnorrkel.rs b/processor/signers/src/wrapped_schnorrkel.rs
index d81eaa70..a84b8d43 100644
--- a/processor/signers/src/wrapped_schnorrkel.rs
+++ b/processor/signers/src/wrapped_schnorrkel.rs
@@ -16,10 +16,10 @@ use frost_schnorrkel::Schnorrkel;
 
 // This wraps a Schnorrkel sign machine into one with a preset message.
 #[derive(Clone)]
-pub(crate) struct WrappedSchnorrkelMachine(ThresholdKeys<Ristretto>, Vec<u8>);
+pub(crate) struct WrappedSchnorrkelMachine(ThresholdKeys<Ristretto>, &'static [u8], Vec<u8>);
 impl WrappedSchnorrkelMachine {
-  pub(crate) fn new(keys: ThresholdKeys<Ristretto>, msg: Vec<u8>) -> Self {
-    Self(keys, msg)
+  pub(crate) fn new(keys: ThresholdKeys<Ristretto>, context: &'static [u8], msg: Vec<u8>) -> Self {
+    Self(keys, context, msg)
   }
 }
 
@@ -39,10 +39,10 @@ impl PreprocessMachine for WrappedSchnorrkelMachine {
     rng: &mut R,
   ) -> (Self::SignMachine, Preprocess<Ristretto, <Schnorrkel as Algorithm<Ristretto>>::Addendum>)
   {
-    let WrappedSchnorrkelMachine(keys, batch) = self;
+    let WrappedSchnorrkelMachine(keys, context, msg) = self;
     let (machine, preprocess) =
-      AlgorithmMachine::new(Schnorrkel::new(b"substrate"), keys).preprocess(rng);
-    (WrappedSchnorrkelSignMachine(machine, batch), preprocess)
+      AlgorithmMachine::new(Schnorrkel::new(context), keys).preprocess(rng);
+    (WrappedSchnorrkelSignMachine(machine, msg), preprocess)
   }
 }
 
diff --git a/substrate/validator-sets/primitives/src/slash_points.rs b/substrate/validator-sets/primitives/src/slash_points.rs
index d420157e..0cc72b2f 100644
--- a/substrate/validator-sets/primitives/src/slash_points.rs
+++ b/substrate/validator-sets/primitives/src/slash_points.rs
@@ -234,9 +234,12 @@ impl TryFrom<Vec<Slash>> for SlashReport {
   }
 }
 
-// This is assumed binding to the ValidatorSet via the key signed with
-pub fn report_slashes_message(slashes: &SlashReport) -> Vec<u8> {
-  (b"ValidatorSets-report_slashes", slashes).encode()
+impl SlashReport {
+  /// The message to sign when publishing this SlashReport.
+  // This is assumed binding to the ValidatorSet via the key signed with
+  pub fn report_slashes_message(&self) -> Vec<u8> {
+    (b"ValidatorSets-report_slashes", &self.0).encode()
+  }
 }
 
 #[test]