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)?; } }