From d5a12a9b977a802413708b6f47bb389e80b9786f Mon Sep 17 00:00:00 2001
From: Luke Parker <lukeparker5132@gmail.com>
Date: Wed, 12 Apr 2023 09:38:20 -0400
Subject: [PATCH] Make TransactionKind have a reference to Signed

Broken commit due to partial staging of one file.
---
 coordinator/src/transaction.rs                | 17 +++++----
 coordinator/tributary/src/tests/block.rs      | 35 +++++++++++++------
 .../tributary/src/tests/transaction/mod.rs    |  6 ++--
 coordinator/tributary/src/transaction.rs      | 12 +++----
 4 files changed, 41 insertions(+), 29 deletions(-)

diff --git a/coordinator/src/transaction.rs b/coordinator/src/transaction.rs
index 0616451c..cc418a79 100644
--- a/coordinator/src/transaction.rs
+++ b/coordinator/src/transaction.rs
@@ -210,18 +210,18 @@ impl ReadWrite for Transaction {
 }
 
 impl TransactionTrait for Transaction {
-  fn kind(&self) -> TransactionKind {
+  fn kind(&self) -> TransactionKind<'_> {
     match self {
-      Transaction::DkgCommitments(_, _, signed) => TransactionKind::Signed(signed.clone()),
-      Transaction::DkgShares(_, _, signed) => TransactionKind::Signed(signed.clone()),
+      Transaction::DkgCommitments(_, _, signed) => TransactionKind::Signed(signed),
+      Transaction::DkgShares(_, _, signed) => TransactionKind::Signed(signed),
 
-      Transaction::SignPreprocess(data) => TransactionKind::Signed(data.signed.clone()),
-      Transaction::SignShare(data) => TransactionKind::Signed(data.signed.clone()),
+      Transaction::SignPreprocess(data) => TransactionKind::Signed(&data.signed),
+      Transaction::SignShare(data) => TransactionKind::Signed(&data.signed),
 
       Transaction::FinalizedBlock(_) => TransactionKind::Provided,
 
-      Transaction::BatchPreprocess(data) => TransactionKind::Signed(data.signed.clone()),
-      Transaction::BatchShare(data) => TransactionKind::Signed(data.signed.clone()),
+      Transaction::BatchPreprocess(data) => TransactionKind::Signed(&data.signed),
+      Transaction::BatchShare(data) => TransactionKind::Signed(&data.signed),
     }
   }
 
@@ -229,8 +229,7 @@ impl TransactionTrait for Transaction {
     let mut tx = self.serialize();
     if let TransactionKind::Signed(signed) = self.kind() {
       // Make sure the part we're cutting off is the signature
-      assert_eq!(&tx[(tx.len() - 64) ..], &signed.signature.serialize());
-      tx.truncate(tx.len() - 64);
+      assert_eq!(tx.drain((tx.len() - 64) ..).collect::<Vec<_>>(), signed.signature.serialize());
     }
     Blake2s256::digest(tx).into()
   }
diff --git a/coordinator/tributary/src/tests/block.rs b/coordinator/tributary/src/tests/block.rs
index ac91904b..1e2c7454 100644
--- a/coordinator/tributary/src/tests/block.rs
+++ b/coordinator/tributary/src/tests/block.rs
@@ -19,15 +19,35 @@ use crate::{
 // A transaction solely defined by its nonce and a distinguisher (to allow creating distinct TXs
 // sharing a nonce).
 #[derive(Clone, PartialEq, Eq, Debug)]
-struct NonceTransaction(u32, u8);
+struct NonceTransaction(u32, u8, Signed);
+
+impl NonceTransaction {
+  fn new(nonce: u32, distinguisher: u8) -> Self {
+    NonceTransaction(
+      nonce,
+      distinguisher,
+      Signed {
+        signer: <Ristretto as Ciphersuite>::G::identity(),
+        nonce,
+        signature: SchnorrSignature::<Ristretto> {
+          R: <Ristretto as Ciphersuite>::G::identity(),
+          s: <Ristretto as Ciphersuite>::F::ZERO,
+        },
+      },
+    )
+  }
+}
 
 impl ReadWrite for NonceTransaction {
   fn read<R: io::Read>(reader: &mut R) -> io::Result<Self> {
     let mut nonce = [0; 4];
     reader.read_exact(&mut nonce)?;
+    let nonce = u32::from_le_bytes(nonce);
+
     let mut distinguisher = [0];
     reader.read_exact(&mut distinguisher)?;
-    Ok(Self(u32::from_le_bytes(nonce), distinguisher[0]))
+
+    Ok(NonceTransaction::new(nonce, distinguisher[0]))
   }
 
   fn write<W: io::Write>(&self, writer: &mut W) -> io::Result<()> {
@@ -37,15 +57,8 @@ impl ReadWrite for NonceTransaction {
 }
 
 impl Transaction for NonceTransaction {
-  fn kind(&self) -> TransactionKind {
-    TransactionKind::Signed(Signed {
-      signer: <Ristretto as Ciphersuite>::G::identity(),
-      nonce: self.0,
-      signature: SchnorrSignature::<Ristretto> {
-        R: <Ristretto as Ciphersuite>::G::identity(),
-        s: <Ristretto as Ciphersuite>::F::ZERO,
-      },
-    })
+  fn kind(&self) -> TransactionKind<'_> {
+    TransactionKind::Signed(&self.2)
   }
 
   fn hash(&self) -> [u8; 32] {
diff --git a/coordinator/tributary/src/tests/transaction/mod.rs b/coordinator/tributary/src/tests/transaction/mod.rs
index cf4e799e..6da9793e 100644
--- a/coordinator/tributary/src/tests/transaction/mod.rs
+++ b/coordinator/tributary/src/tests/transaction/mod.rs
@@ -51,7 +51,7 @@ impl ReadWrite for ProvidedTransaction {
 }
 
 impl Transaction for ProvidedTransaction {
-  fn kind(&self) -> TransactionKind {
+  fn kind(&self) -> TransactionKind<'_> {
     TransactionKind::Provided
   }
 
@@ -91,8 +91,8 @@ impl ReadWrite for SignedTransaction {
 }
 
 impl Transaction for SignedTransaction {
-  fn kind(&self) -> TransactionKind {
-    TransactionKind::Signed(self.1.clone())
+  fn kind(&self) -> TransactionKind<'_> {
+    TransactionKind::Signed(&self.1)
   }
 
   fn hash(&self) -> [u8; 32] {
diff --git a/coordinator/tributary/src/transaction.rs b/coordinator/tributary/src/transaction.rs
index 50562c3d..1d4416f5 100644
--- a/coordinator/tributary/src/transaction.rs
+++ b/coordinator/tributary/src/transaction.rs
@@ -53,7 +53,7 @@ impl ReadWrite for Signed {
 
 #[allow(clippy::large_enum_variant)]
 #[derive(Clone, PartialEq, Eq, Debug)]
-pub enum TransactionKind {
+pub enum TransactionKind<'a> {
   /// This tranaction should be provided by every validator, solely ordered by the block producer.
   ///
   /// This transaction is only valid if a supermajority of validators provided it.
@@ -63,11 +63,11 @@ pub enum TransactionKind {
   Unsigned,
 
   /// A signed transaction.
-  Signed(Signed),
+  Signed(&'a Signed),
 }
 
 pub trait Transaction: Send + Sync + Clone + Eq + Debug + ReadWrite {
-  fn kind(&self) -> TransactionKind;
+  fn kind(&self) -> TransactionKind<'_>;
   /// Return the hash of this transaction.
   ///
   /// The hash must NOT commit to the signature.
@@ -97,13 +97,13 @@ pub(crate) fn verify_transaction<T: Transaction>(
     TransactionKind::Unsigned => {}
     TransactionKind::Signed(Signed { signer, nonce, signature }) => {
       // TODO: Use presence as a whitelist, erroring on lack of
-      if next_nonces.get(&signer).cloned().unwrap_or(0) != nonce {
+      if next_nonces.get(signer).cloned().unwrap_or(0) != *nonce {
         Err(TransactionError::Temporal)?;
       }
-      next_nonces.insert(signer, nonce + 1);
+      next_nonces.insert(*signer, nonce + 1);
 
       // TODO: Use Schnorr half-aggregation and a batch verification here
-      if !signature.verify(signer, tx.sig_hash(genesis)) {
+      if !signature.verify(*signer, tx.sig_hash(genesis)) {
         Err(TransactionError::Fatal)?;
       }
     }