diff --git a/common/blockchain/src/block.rs b/common/blockchain/src/block.rs index b4c92012..b826c613 100644 --- a/common/blockchain/src/block.rs +++ b/common/blockchain/src/block.rs @@ -69,17 +69,19 @@ impl Block { /// Signs the block. - pub fn sign(&self, signer: &S) -> PK::Signature - where - S: crate::validators::Signer, - { + pub fn sign(&self, signer: &impl crate::Signer) -> PK::Signature { signer.sign(self.calc_hash().as_slice()) } /// Verifies signature for the block. #[inline] - pub fn verify(&self, pk: &PK, signature: &PK::Signature) -> bool { - pk.verify(self.calc_hash().as_slice(), signature) + pub fn verify( + &self, + pubkey: &PK, + signature: &PK::Signature, + verifier: &impl crate::Verifier, + ) -> bool { + verifier.verify(self.calc_hash().as_slice(), pubkey, signature) } /// Constructs next block. @@ -179,14 +181,14 @@ fn test_block_generation() { let signer = MockSigner(pk); let signature = genesis.sign(&signer); assert_eq!(MockSignature(1722674425, pk), signature); - assert!(genesis.verify(&pk, &signature)); - assert!(!genesis.verify(&MockPubKey(88), &signature)); - assert!(!genesis.verify(&pk, &MockSignature(0, pk))); + assert!(genesis.verify(&pk, &signature, &())); + assert!(!genesis.verify(&MockPubKey(88), &signature, &())); + assert!(!genesis.verify(&pk, &MockSignature(0, pk), &())); let mut block = genesis.clone(); block.host_timestamp += 1; assert_ne!(genesis_hash, block.calc_hash()); - assert!(!block.verify(&pk, &signature)); + assert!(!block.verify(&pk, &signature, &())); // Try creating invalid next block. assert_eq!( diff --git a/common/blockchain/src/lib.rs b/common/blockchain/src/lib.rs index 1161cf3c..4a68e12a 100644 --- a/common/blockchain/src/lib.rs +++ b/common/blockchain/src/lib.rs @@ -19,4 +19,4 @@ pub use config::Config; pub use epoch::Epoch; pub use height::{BlockDelta, BlockHeight, HostDelta, HostHeight}; pub use manager::ChainManager; -pub use validators::{PubKey, Signer, Validator}; +pub use validators::{PubKey, Signer, Validator, Verifier}; diff --git a/common/blockchain/src/manager.rs b/common/blockchain/src/manager.rs index d612784d..3d26cb04 100644 --- a/common/blockchain/src/manager.rs +++ b/common/blockchain/src/manager.rs @@ -199,26 +199,27 @@ impl ChainManager { &mut self, pubkey: PK, signature: &PK::Signature, + verifier: &impl crate::Verifier, ) -> Result { let pending = self .pending_block .as_mut() .ok_or(AddSignatureError::NoPendingBlock)?; - if pending.signers.contains(&pubkey) { - return Ok(false); - } - if !pubkey.verify(pending.hash.as_slice(), signature) { - return Err(AddSignatureError::BadSignature); - } - - pending.signing_stake += self + let validator_stake = self .next_epoch .validator(&pubkey) .ok_or(AddSignatureError::BadValidator)? .stake() .get(); - assert!(pending.signers.insert(pubkey)); + if !verifier.verify(pending.hash.as_slice(), &pubkey, signature) { + return Err(AddSignatureError::BadSignature); + } + + if !pending.signers.insert(pubkey) { + return Ok(false); + } + pending.signing_stake += validator_stake; if pending.signing_stake < self.next_epoch.quorum_stake().get() { return Ok(false); } @@ -304,7 +305,7 @@ fn test_generate() { validator: &crate::validators::Validator, ) -> Result { let signature = mgr.head().1.sign(&validator.pubkey().make_signer()); - mgr.add_signature(validator.pubkey().clone(), &signature) + mgr.add_signature(validator.pubkey().clone(), &signature, &()) } // The head hasn’t been fully signed yet. @@ -329,11 +330,11 @@ fn test_generate() { let signature = mgr.head().1.sign(&pubkey.make_signer()); assert_eq!( Err(AddSignatureError::BadValidator), - mgr.add_signature(pubkey, &signature) + mgr.add_signature(pubkey, &signature, &()) ); assert_eq!( Err(AddSignatureError::BadSignature), - mgr.add_signature(bob.pubkey().clone(), &signature) + mgr.add_signature(bob.pubkey().clone(), &signature, &()) ); assert_eq!( diff --git a/common/blockchain/src/validators.rs b/common/blockchain/src/validators.rs index 80f18d70..11ee6c79 100644 --- a/common/blockchain/src/validators.rs +++ b/common/blockchain/src/validators.rs @@ -12,17 +12,23 @@ pub trait PubKey: { /// Signature corresponding to this public key type. type Signature: Clone + borsh::BorshSerialize + borsh::BorshDeserialize; - - /// Verifies the signature for given message. - fn verify(&self, message: &[u8], signature: &Self::Signature) -> bool; } -pub trait Signer { - /// Signature created by this signer. - type Signature: Clone + borsh::BorshSerialize + borsh::BorshDeserialize; +/// Function verifying a signature. +pub trait Verifier { + /// Verify signature for given message. + fn verify( + &self, + message: &[u8], + pubkey: &PK, + signature: &PK::Signature, + ) -> bool; +} +/// Function generating signatures. +pub trait Signer { /// Signs given message. - fn sign(&self, message: &[u8]) -> Self::Signature; + fn sign(&self, message: &[u8]) -> PK::Signature; } /// A validator @@ -115,16 +121,24 @@ pub(crate) mod test_utils { impl super::PubKey for MockPubKey { type Signature = MockSignature; + } - fn verify(&self, message: &[u8], signature: &Self::Signature) -> bool { - signature.0 == short_hash(message) && &signature.1 == self + impl super::Verifier for () { + fn verify( + &self, + message: &[u8], + pubkey: &MockPubKey, + signature: &::Signature, + ) -> bool { + signature.0 == short_hash(message) && &signature.1 == pubkey } } - impl super::Signer for MockSigner { - type Signature = MockSignature; - - fn sign(&self, message: &[u8]) -> Self::Signature { + impl super::Signer for MockSigner { + fn sign( + &self, + message: &[u8], + ) -> ::Signature { MockSignature(short_hash(message), self.0) } }